Merge branch 'master' into 5.x

Conflicts:
	CHANGES.md
	csv/src/main/java/org/apache/metamodel/csv/CsvDataContext.java
diff --git a/.travis.yml b/.travis.yml
index 46a372d..33b571c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,6 @@
 sudo: false
 language: java
 jdk:
-  - openjdk7
   - oraclejdk8
   
 before_install:
diff --git a/CHANGES.md b/CHANGES.md
index d5943fd..a468ab1 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,10 @@
+### Apache MetaModel 5.0
+
+ * [METAMODEL-6] - Added update summary containing information about changes on returning UpdateableDataContext.executeUpdate(..)
+ * [METAMODEL-63] - Added UnionDataSet, a general purpose utility for doing client-side unions from other queries or data sets.
+ * [METAMODEL-222] - Added support for Java 8 lambdas, removed support for Java 7.
+ * [METAMODEL-1087] - Removed deprecated APIs from MetaModel's codebase.
+ * [METAMODEL-1139] - Employed Java 8 functional types (java.util.function) in favor of (now deprecated) Ref, Action, Func. 
  * [METAMODEL-1140] - Allowed SalesforceDataContext without a security token.
  * [METAMODEL-1141] - Added RFC 4180 compliant CSV parsing.
 
diff --git a/cassandra/pom.xml b/cassandra/pom.xml
index af8c914..04a6543 100644
--- a/cassandra/pom.xml
+++ b/cassandra/pom.xml
@@ -13,7 +13,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-cassandra</artifactId>
diff --git a/core/pom.xml b/core/pom.xml
index a4e0f8e..3af58c9 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-core</artifactId>
diff --git a/core/src/main/java/org/apache/metamodel/AbstractUpdateCallback.java b/core/src/main/java/org/apache/metamodel/AbstractUpdateCallback.java
index 472fb6f..a1c2f1a 100644
--- a/core/src/main/java/org/apache/metamodel/AbstractUpdateCallback.java
+++ b/core/src/main/java/org/apache/metamodel/AbstractUpdateCallback.java
@@ -43,21 +43,21 @@
     @Override
     public TableCreationBuilder createTable(String schemaName, String tableName) throws IllegalArgumentException,
             IllegalStateException {
-        Schema schema = getSchema(schemaName);
+        final Schema schema = getSchema(schemaName);
         return createTable(schema, tableName);
     }
 
     @Override
-    public TableDropBuilder dropTable(String schemaName, String tableName) throws IllegalArgumentException,
+    public final TableDropBuilder dropTable(String schemaName, String tableName) throws IllegalArgumentException,
             IllegalStateException, UnsupportedOperationException {
-        Table table = getTable(schemaName, tableName);
+        final Table table = getTable(schemaName, tableName);
         return dropTable(table);
     }
 
     @Override
-    public TableDropBuilder dropTable(Schema schema, String tableName) throws IllegalArgumentException,
+    public final TableDropBuilder dropTable(Schema schema, String tableName) throws IllegalArgumentException,
             IllegalStateException, UnsupportedOperationException {
-        Table table = schema.getTableByName(tableName);
+        final Table table = schema.getTableByName(tableName);
         if (table == null) {
             throw new IllegalArgumentException("Nu such table '" + tableName + "' found in schema: " + schema
                     + ". Available tables are: " + Arrays.toString(schema.getTableNames()));
@@ -72,7 +72,7 @@
     }
 
     @Override
-    public RowInsertionBuilder insertInto(String schemaName, String tableName) throws IllegalArgumentException,
+    public final RowInsertionBuilder insertInto(String schemaName, String tableName) throws IllegalArgumentException,
             IllegalStateException, UnsupportedOperationException {
         return insertInto(getTable(schemaName, tableName));
     }
@@ -101,7 +101,7 @@
     }
 
     @Override
-    public RowDeletionBuilder deleteFrom(String schemaName, String tableName) throws IllegalArgumentException,
+    public final RowDeletionBuilder deleteFrom(String schemaName, String tableName) throws IllegalArgumentException,
             IllegalStateException, UnsupportedOperationException {
         final Table table = getTable(schemaName, tableName);
         return deleteFrom(table);
@@ -138,7 +138,7 @@
 
     @Override
     public boolean isInsertSupported() {
-        // since 2.0 all updateable datacontext have create table support
+        // since 2.0 all updateable datacontext have insert into table support
         return true;
     }
 
@@ -148,7 +148,7 @@
     }
 
     @Override
-    public RowUpdationBuilder update(String schemaName, String tableName) throws IllegalArgumentException,
+    public final RowUpdationBuilder update(String schemaName, String tableName) throws IllegalArgumentException,
             IllegalStateException, UnsupportedOperationException {
         final Table table = getTable(schemaName, tableName);
         return update(table);
@@ -159,4 +159,8 @@
             UnsupportedOperationException {
         return new DeleteAndInsertBuilder(this, table);
     }
+    
+    public UpdateSummary getUpdateSummary() {
+        return DefaultUpdateSummary.unknownUpdates();
+    }
 }
diff --git a/core/src/main/java/org/apache/metamodel/CompositeDataContext.java b/core/src/main/java/org/apache/metamodel/CompositeDataContext.java
index c7b6ee3..8612a51 100644
--- a/core/src/main/java/org/apache/metamodel/CompositeDataContext.java
+++ b/core/src/main/java/org/apache/metamodel/CompositeDataContext.java
@@ -27,6 +27,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.query.FromItem;
@@ -34,10 +35,10 @@
 import org.apache.metamodel.schema.CompositeSchema;
 import org.apache.metamodel.schema.Schema;
 import org.apache.metamodel.schema.Table;
-import org.apache.metamodel.util.Func;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 /**
  * DataContext for composite datacontexts. Composite DataContexts wrap several
  * other datacontexts and makes cross-datastore querying possible.
@@ -92,12 +93,7 @@
         } else {
             // we create a datacontext which can materialize tables from
             // separate datacontexts.
-            final Func<Table, DataContext> dataContextRetrievalFunction = new Func<Table, DataContext>() {
-                @Override
-                public DataContext eval(Table table) {
-                    return getDataContext(table);
-                }
-            };
+            final Function<Table, DataContext> dataContextRetrievalFunction = table -> getDataContext(table);
             return new CompositeQueryDelegate(dataContextRetrievalFunction).executeQuery(query);
         }
     }
diff --git a/core/src/main/java/org/apache/metamodel/CompositeQueryDelegate.java b/core/src/main/java/org/apache/metamodel/CompositeQueryDelegate.java
index 9a3517a..d3e1a04 100644
--- a/core/src/main/java/org/apache/metamodel/CompositeQueryDelegate.java
+++ b/core/src/main/java/org/apache/metamodel/CompositeQueryDelegate.java
@@ -18,18 +18,19 @@
  */
 package org.apache.metamodel;
 
+import java.util.function.Function;
+
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.query.Query;
 import org.apache.metamodel.schema.Column;
 import org.apache.metamodel.schema.Table;
-import org.apache.metamodel.util.Func;
 
 final class CompositeQueryDelegate extends QueryPostprocessDelegate {
 
-	private final Func<Table, DataContext> _dataContextRetrievalFunction;
+	private final Function<Table, DataContext> _dataContextRetrievalFunction;
 
 	public CompositeQueryDelegate(
-			Func<Table, DataContext> dataContextRetrievalFunction) {
+			Function<Table, DataContext> dataContextRetrievalFunction) {
 		_dataContextRetrievalFunction = dataContextRetrievalFunction;
 	}
 
@@ -38,8 +39,8 @@
 			int maxRows) {
 		// find the appropriate datacontext to execute a simple
 		// table materialization query
-		DataContext dc = _dataContextRetrievalFunction.eval(table);
-		Query q = new Query().select(columns).from(table);
+		final DataContext dc = _dataContextRetrievalFunction.apply(table);
+		final Query q = new Query().select(columns).from(table);
 		if (maxRows >= 0) {
 			q.setMaxRows(maxRows);
 		}
diff --git a/core/src/main/java/org/apache/metamodel/DefaultUpdateSummary.java b/core/src/main/java/org/apache/metamodel/DefaultUpdateSummary.java
new file mode 100644
index 0000000..bc8ec27
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/DefaultUpdateSummary.java
@@ -0,0 +1,74 @@
+/**
+ * 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;
+
+import java.util.Optional;
+
+/**
+ * Default implementation of {@link UpdateSummary}.
+ */
+public class DefaultUpdateSummary implements UpdateSummary {
+
+    private static final UpdateSummary UNKNOWN_UPDATES = new DefaultUpdateSummary(null, null, null, null);
+
+    /**
+     * Gets an {@link UpdateSummary} object to return when the extent of the
+     * updates are unknown.
+     * 
+     * @return a {@link UpdateSummary} object without any knowledge of updates
+     *         performed.
+     */
+    public static UpdateSummary unknownUpdates() {
+        return UNKNOWN_UPDATES;
+    }
+
+    private final Integer _insertedRows;
+    private final Integer _updatedRows;
+    private final Integer _deletedRows;
+    private final Iterable<Object> _generatedKeys;
+
+    public DefaultUpdateSummary(Integer insertedRows, Integer updatedRows, Integer deletedRows,
+            Iterable<Object> generatedKeys) {
+        _insertedRows = insertedRows;
+        _updatedRows = updatedRows;
+        _deletedRows = deletedRows;
+        _generatedKeys = generatedKeys;
+    }
+
+    @Override
+    public Optional<Integer> getInsertedRows() {
+        return Optional.ofNullable(_insertedRows);
+    }
+
+    @Override
+    public Optional<Integer> getUpdatedRows() {
+        return Optional.ofNullable(_updatedRows);
+    }
+
+    @Override
+    public Optional<Integer> getDeletedRows() {
+        return Optional.ofNullable(_deletedRows);
+    }
+
+    @Override
+    public Optional<Iterable<Object>> getGeneratedKeys() {
+        return Optional.ofNullable(_generatedKeys);
+    }
+
+}
diff --git a/core/src/main/java/org/apache/metamodel/MetaModelHelper.java b/core/src/main/java/org/apache/metamodel/MetaModelHelper.java
index 7ffa870..09d47bc 100644
--- a/core/src/main/java/org/apache/metamodel/MetaModelHelper.java
+++ b/core/src/main/java/org/apache/metamodel/MetaModelHelper.java
@@ -58,9 +58,7 @@
 import org.apache.metamodel.schema.Table;
 import org.apache.metamodel.util.AggregateBuilder;
 import org.apache.metamodel.util.CollectionUtils;
-import org.apache.metamodel.util.Func;
 import org.apache.metamodel.util.ObjectComparator;
-import org.apache.metamodel.util.Predicate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -248,11 +246,8 @@
     }
 
     public static DataSet getFiltered(DataSet dataSet, Iterable<FilterItem> filterItems) {
-        List<IRowFilter> filters = CollectionUtils.map(filterItems, new Func<FilterItem, IRowFilter>() {
-            @Override
-            public IRowFilter eval(FilterItem filterItem) {
-                return filterItem;
-            }
+        List<IRowFilter> filters = CollectionUtils.map(filterItems, filterItem -> {
+            return filterItem;
         });
         if (filters.isEmpty()) {
             return dataSet;
@@ -278,8 +273,8 @@
 
         for (SelectItem selectItem : selectItems) {
             if (selectItem.getScalarFunction() != null) {
-                if (!dataSetSelectItems.contains(selectItem)
-                        && dataSetSelectItems.contains(selectItem.replaceFunction(null))) {
+                if (!dataSetSelectItems.contains(selectItem) && dataSetSelectItems.contains(selectItem.replaceFunction(
+                        null))) {
                     scalarFunctionSelectItemsToEvaluate.add(selectItem);
                 }
             }
@@ -314,8 +309,8 @@
             }
             final DataSetHeader groupByHeader = new CachingDataSetHeader(groupBySelects);
 
-            // Creates a list of SelectItems that have functions
-            List<SelectItem> functionItems = getFunctionSelectItems(selectItems);
+            // Creates a list of SelectItems that have aggregate functions
+            List<SelectItem> functionItems = getAggregateFunctionSelectItems(selectItems);
 
             // Loop through the dataset and identify groups
             while (dataSet.next()) {
@@ -508,39 +503,15 @@
         return new InMemoryDataSet(header, resultRows);
     }
 
-    /**
-     * 
-     * @param selectItems
-     * @return
-     * 
-     * @deprecated use {@link #getAggregateFunctionSelectItems(Iterable)} or
-     *             {@link #getScalarFunctionSelectItems(Iterable)} instead
-     */
-    @Deprecated
-    public static List<SelectItem> getFunctionSelectItems(Iterable<SelectItem> selectItems) {
-        return CollectionUtils.filter(selectItems, new Predicate<SelectItem>() {
-            @Override
-            public Boolean eval(SelectItem arg) {
-                return arg.getFunction() != null;
-            }
-        });
-    }
-
     public static List<SelectItem> getAggregateFunctionSelectItems(Iterable<SelectItem> selectItems) {
-        return CollectionUtils.filter(selectItems, new Predicate<SelectItem>() {
-            @Override
-            public Boolean eval(SelectItem arg) {
-                return arg.getAggregateFunction() != null;
-            }
+        return CollectionUtils.filter(selectItems, arg -> {
+            return arg.getAggregateFunction() != null;
         });
     }
 
     public static List<SelectItem> getScalarFunctionSelectItems(Iterable<SelectItem> selectItems) {
-        return CollectionUtils.filter(selectItems, new Predicate<SelectItem>() {
-            @Override
-            public Boolean eval(SelectItem arg) {
-                return arg.getScalarFunction() != null;
-            }
+        return CollectionUtils.filter(selectItems, arg -> {
+            return arg.getScalarFunction() != null;
         });
     }
 
@@ -716,10 +687,9 @@
             List<Row> ds1rows = new ArrayList<Row>();
             ds1rows.add(ds1row);
 
-            DataSet carthesianProduct = getCarthesianProduct(
-                    new DataSet[] { new InMemoryDataSet(new CachingDataSetHeader(si1), ds1rows),
-                            new InMemoryDataSet(new CachingDataSetHeader(si2), ds2data) },
-                    onConditions);
+            DataSet carthesianProduct = getCarthesianProduct(new DataSet[] { new InMemoryDataSet(
+                    new CachingDataSetHeader(si1), ds1rows), new InMemoryDataSet(new CachingDataSetHeader(si2),
+                            ds2data) }, onConditions);
             List<Row> carthesianRows = readDataSetFull(carthesianProduct);
             if (carthesianRows.size() > 0) {
                 resultRows.addAll(carthesianRows);
@@ -787,20 +757,14 @@
     }
 
     public static Column[] getColumnsByType(Column[] columns, final ColumnType columnType) {
-        return CollectionUtils.filter(columns, new Predicate<Column>() {
-            @Override
-            public Boolean eval(Column column) {
-                return column.getType() == columnType;
-            }
+        return CollectionUtils.filter(columns, column -> {
+            return column.getType() == columnType;
         }).toArray(new Column[0]);
     }
 
     public static Column[] getColumnsBySuperType(Column[] columns, final SuperColumnType superColumnType) {
-        return CollectionUtils.filter(columns, new Predicate<Column>() {
-            @Override
-            public Boolean eval(Column column) {
-                return column.getType().getSuperType() == superColumnType;
-            }
+        return CollectionUtils.filter(columns, column -> {
+            return column.getType().getSuperType() == superColumnType;
         }).toArray(new Column[0]);
     }
 
diff --git a/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java b/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java
index c7dcfb7..fac70d0 100644
--- a/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java
+++ b/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java
@@ -167,12 +167,6 @@
 
                     // check for simple queries with or without simple criteria
                     if (orderByItems.isEmpty()) {
-                        // no WHERE criteria set
-                        if (whereItems.isEmpty()) {
-                            final DataSet dataSet = materializeTable(table, selectItems, firstRow, maxRows);
-                            return dataSet;
-                        }
-
                         final DataSet dataSet = materializeTable(table, selectItems, whereItems, firstRow, maxRows);
                         return dataSet;
                     }
@@ -313,7 +307,7 @@
 
             // Dispatching to the concrete subclass of
             // QueryPostprocessDataContextStrategy
-            dataSet = materializeTable(table, selectItemsToMaterialize, 1, -1);
+            dataSet = materializeTable(table, selectItemsToMaterialize, Collections.emptyList(), 1, -1);
 
         } else if (joinType != null) {
             // We need to (recursively) materialize a joined FromItem
@@ -438,12 +432,6 @@
         return false;
     }
 
-    @Deprecated
-    protected DataSet materializeTable(final Table table, final List<SelectItem> selectItems, final int firstRow,
-            final int maxRows) {
-        return materializeTable(table, selectItems, Collections.<FilterItem> emptyList(), firstRow, maxRows);
-    }
-
     protected boolean isMainSchemaTable(Table table) {
         Schema schema = table.getSchema();
         if (INFORMATION_SCHEMA_NAME.equals(schema.getName())) {
@@ -600,17 +588,6 @@
     }
 
     /**
-     * 
-     * @return
-     * 
-     * @deprecated use {@link #getDefaultSchema()} instead
-     */
-    @Deprecated
-    protected Schema getMainSchemaInternal() {
-        return getDefaultSchema();
-    }
-
-    /**
      * Adds a {@link TypeConverter} to this DataContext's query engine (Query
      * Postprocessor) for read operations. Note that this method should NOT be
      * invoked directly by consuming code. Rather use
diff --git a/core/src/main/java/org/apache/metamodel/UpdateScript.java b/core/src/main/java/org/apache/metamodel/UpdateScript.java
index 44be200..bc344ff 100644
--- a/core/src/main/java/org/apache/metamodel/UpdateScript.java
+++ b/core/src/main/java/org/apache/metamodel/UpdateScript.java
@@ -18,8 +18,6 @@
  */
 package org.apache.metamodel;
 
-import org.apache.metamodel.util.Action;
-
 /**
  * Represents any updating operation or update script that can be executed on a
  * {@link UpdateableDataContext}. Users of MetaModel should implement their own
@@ -27,13 +25,13 @@
  * {@link UpdateableDataContext#executeUpdate(UpdateScript)} method for
  * execution.
  */
-public interface UpdateScript extends Action<UpdateCallback> {
+@FunctionalInterface
+public interface UpdateScript {
 
 	/**
 	 * Invoked by MetaModel when the update script should be run. User should
 	 * implement this method and invoke update operations on the
 	 * {@link UpdateCallback}.
 	 */
-	@Override
 	public void run(UpdateCallback callback);
 }
diff --git a/core/src/main/java/org/apache/metamodel/UpdateSummary.java b/core/src/main/java/org/apache/metamodel/UpdateSummary.java
new file mode 100644
index 0000000..fc7239b
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/UpdateSummary.java
@@ -0,0 +1,65 @@
+/**
+ * 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;
+
+import java.util.Optional;
+
+/**
+ * Represents a summary of changes made in a given
+ * {@link UpdateableDataContext#executeUpdate(UpdateScript)} call.
+ * 
+ * The amount of information available from an update varies a lot between
+ * different implementations of {@link UpdateableDataContext}. This interface
+ * represents the most common elements of interest, but not all elements may be
+ * available for a given update. For this reason any method call on this
+ * interface should be considered not guaranteed to return a value (so expect
+ * nulls to represent "not known/available").
+ */
+public interface UpdateSummary {
+
+    /**
+     * Gets the number of inserted rows, or null if this number is unknown.
+     * 
+     * @return an optional row count.
+     */
+    public Optional<Integer> getInsertedRows();
+
+    /**
+     * Gets the number of updated rows, or null if this number is unknown.
+     * 
+     * @return an optional row count.
+     */
+    public Optional<Integer> getUpdatedRows();
+
+    /**
+     * Gets the number of deleted rows, or null if this number is unknown.
+     * 
+     * @return an optional row count.
+     */
+    public Optional<Integer> getDeletedRows();
+
+    /**
+     * Gets a collection of keys that was generated as part of the update -
+     * typically because INSERTs where executed on an underlying database which
+     * generated record IDs for each insert.
+     * 
+     * @return an optional collection of generated keys.
+     */
+    public Optional<Iterable<Object>> getGeneratedKeys();
+}
diff --git a/core/src/main/java/org/apache/metamodel/UpdateSummaryBuilder.java b/core/src/main/java/org/apache/metamodel/UpdateSummaryBuilder.java
new file mode 100644
index 0000000..6469a1b
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/UpdateSummaryBuilder.java
@@ -0,0 +1,130 @@
+/**
+ * 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;
+
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * A builder object for {@link UpdateSummary}.
+ */
+public class UpdateSummaryBuilder {
+
+    private int _inserts;
+    private int _updates;
+    private int _deletes;
+    private Set<Object> _generatedKeys;
+
+    public UpdateSummaryBuilder() {
+    }
+
+    public UpdateSummary build() {
+        final Integer insertedRows = (_inserts == -1 ? null : _inserts);
+        final Integer updatedRows = (_updates == -1 ? null : _updates);
+        final Integer deletedRows = (_deletes == -1 ? null : _deletes);
+        final Iterable<Object> generatedKeys;
+        if (_generatedKeys != null) {
+            generatedKeys = new LinkedHashSet<>(_generatedKeys);
+        } else {
+            generatedKeys = null;
+        }
+        return new DefaultUpdateSummary(insertedRows, updatedRows, deletedRows, generatedKeys);
+    }
+
+    public UpdateSummaryBuilder addInsert() {
+        return addInserts(1);
+    }
+
+    public UpdateSummaryBuilder addInserts(int inserts) {
+        if (_inserts != -1) {
+            _inserts += inserts;
+        }
+        return this;
+    }
+
+    public UpdateSummaryBuilder makeInsertsUnknown() {
+        _inserts = -1;
+        return this;
+    }
+
+    public UpdateSummaryBuilder addUpdate() {
+        return addUpdates(1);
+    }
+
+    public UpdateSummaryBuilder addUpdates(int updates) {
+        if (_updates != -1) {
+            _updates += updates;
+        }
+        return this;
+    }
+
+    public UpdateSummaryBuilder makeUpdatesUnknown() {
+        _updates = -1;
+        return this;
+    }
+
+    public UpdateSummaryBuilder addDelete() {
+        return addDeletes(1);
+    }
+
+    public UpdateSummaryBuilder addDeletes(int deletes) {
+        if (_deletes != -1) {
+            _deletes += deletes;
+        }
+        return this;
+    }
+
+    public UpdateSummaryBuilder makeDeletesUnknown() {
+        _deletes = -1;
+        return this;
+    }
+
+    public UpdateSummaryBuilder addGeneratedKey(Object key) {
+        if (_generatedKeys == null) {
+            _generatedKeys = new HashSet<>();
+        }
+        _generatedKeys.add(key);
+        return this;
+    }
+
+    public UpdateSummaryBuilder addGeneratedKeys(Object... keys) {
+        if (_generatedKeys == null) {
+            _generatedKeys = new HashSet<>();
+        }
+        for (Object key : keys) {
+            _generatedKeys.add(key);
+        }
+        return this;
+    }
+
+    public UpdateSummaryBuilder addGeneratedKeys(Iterable<?> keys) {
+        if (_generatedKeys == null) {
+            _generatedKeys = new HashSet<>();
+        }
+        for (Object key : keys) {
+            _generatedKeys.add(key);
+        }
+        return this;
+    }
+
+    public UpdateSummaryBuilder makeGeneratedKeysUnknown() {
+        _generatedKeys = null;
+        return this;
+    }
+}
diff --git a/core/src/main/java/org/apache/metamodel/UpdateableDataContext.java b/core/src/main/java/org/apache/metamodel/UpdateableDataContext.java
index 09bd234..6c369ea 100644
--- a/core/src/main/java/org/apache/metamodel/UpdateableDataContext.java
+++ b/core/src/main/java/org/apache/metamodel/UpdateableDataContext.java
@@ -23,17 +23,18 @@
  */
 public interface UpdateableDataContext extends DataContext {
 
-	/**
-	 * Submits an {@link UpdateScript} for execution on the {@link DataContext}.
-	 * 
-	 * Since implementations of the {@link DataContext} vary quite a lot, there
-	 * is no golden rule as to how an update script will be executed. But the
-	 * implementors should strive towards handling an {@link UpdateScript} as a
-	 * single transactional change to the data store.
-	 * 
-	 * @param update
-	 *            the update script to execute
-	 */
-	public void executeUpdate(UpdateScript update);
+    /**
+     * Submits an {@link UpdateScript} for execution on the {@link DataContext}.
+     * 
+     * Since implementations of the {@link DataContext} vary quite a lot, there
+     * is no golden rule as to how an update script will be executed. But the
+     * implementors should strive towards handling an {@link UpdateScript} as a
+     * single transactional change to the data store.
+     * 
+     * @param update
+     *            the update script to execute
+     * @return a summary of the updates performed
+     */
+    public UpdateSummary executeUpdate(UpdateScript update);
 
 }
diff --git a/core/src/main/java/org/apache/metamodel/convert/StringToDateConverter.java b/core/src/main/java/org/apache/metamodel/convert/StringToDateConverter.java
index ed7704e..b27e3b2 100644
--- a/core/src/main/java/org/apache/metamodel/convert/StringToDateConverter.java
+++ b/core/src/main/java/org/apache/metamodel/convert/StringToDateConverter.java
@@ -22,8 +22,8 @@
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.function.Function;
 
-import org.apache.metamodel.util.Func;
 import org.apache.metamodel.util.TimeComparator;
 
 /**
@@ -32,93 +32,79 @@
  */
 public class StringToDateConverter implements TypeConverter<String, Date> {
 
-	private final Func<Date, String> _serializeFunc;
-	private final Func<String, Date> _deserializeFunc;
+    private final Function<Date, String> _serializeFunc;
+    private final Function<String, Date> _deserializeFunc;
 
-	/**
-	 * Constructs a new {@link StringToDateConverter} which will use the
-	 * {@link TimeComparator#toDate(Object)} method for parsing dates and the
-	 * {@link DateFormat#MEDIUM} date time format for physical representation.
-	 */
-	public StringToDateConverter() {
-		_deserializeFunc = new Func<String, Date>() {
-			@Override
-			public Date eval(String stringValue) {
-				return TimeComparator.toDate(stringValue);
-			}
-		};
-		_serializeFunc = new Func<Date, String>() {
-			@Override
-			public String eval(Date date) {
-				return DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
-						DateFormat.MEDIUM).format(date);
-			}
-		};
-	}
+    /**
+     * Constructs a new {@link StringToDateConverter} which will use the
+     * {@link TimeComparator#toDate(Object)} method for parsing dates and the
+     * {@link DateFormat#MEDIUM} date time format for physical representation.
+     */
+    public StringToDateConverter() {
+        _deserializeFunc = stringValue -> {
+            return TimeComparator.toDate(stringValue);
+        };
+        _serializeFunc = date -> {
+            return DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).format(date);
+        };
+    }
 
-	/**
-	 * Constructs a new {@link StringToDateConverter} using a given date
-	 * pattern.
-	 * 
-	 * @param datePattern
-	 *            a String date pattern, corresponding to the syntax of a
-	 *            {@link SimpleDateFormat}.
-	 */
-	public StringToDateConverter(String datePattern) {
-		this(new SimpleDateFormat(datePattern));
-	}
+    /**
+     * Constructs a new {@link StringToDateConverter} using a given date
+     * pattern.
+     * 
+     * @param datePattern
+     *            a String date pattern, corresponding to the syntax of a
+     *            {@link SimpleDateFormat}.
+     */
+    public StringToDateConverter(String datePattern) {
+        this(new SimpleDateFormat(datePattern));
+    }
 
-	/**
-	 * Constructs a new {@link StringToDateConverter} using a given
-	 * {@link DateFormat}.
-	 * 
-	 * @param dateFormat
-	 *            the {@link DateFormat} to use for parsing and formatting
-	 *            dates.
-	 */
-	public StringToDateConverter(final DateFormat dateFormat) {
-		if (dateFormat == null) {
-			throw new IllegalArgumentException("DateFormat cannot be null");
-		}
-		_deserializeFunc = new Func<String, Date>() {
-			@Override
-			public Date eval(String string) {
-				try {
-					return dateFormat.parse(string);
-				} catch (ParseException e) {
-					throw new IllegalArgumentException(
-							"Could not parse date string: " + string);
-				}
-			}
-		};
-		_serializeFunc = new Func<Date, String>() {
-			@Override
-			public String eval(Date date) {
-				return dateFormat.format(date);
-			}
-		};
-	}
+    /**
+     * Constructs a new {@link StringToDateConverter} using a given
+     * {@link DateFormat}.
+     * 
+     * @param dateFormat
+     *            the {@link DateFormat} to use for parsing and formatting
+     *            dates.
+     */
+    public StringToDateConverter(final DateFormat dateFormat) {
+        if (dateFormat == null) {
+            throw new IllegalArgumentException("DateFormat cannot be null");
+        }
+        _deserializeFunc = string -> {
+            try {
+                return dateFormat.parse(string);
+            } catch (ParseException e) {
+                throw new IllegalArgumentException("Could not parse date string: " + string);
+            }
+        };
+        _serializeFunc = date -> {
+            return dateFormat.format(date);
+        };
+    }
 
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public String toPhysicalValue(Date virtualValue) {
-		if (virtualValue == null) {
-			return null;
-		}
-		return _serializeFunc.eval(virtualValue);
-	}
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toPhysicalValue(Date virtualValue) {
+        if (virtualValue == null) {
+            return null;
+        }
+        return _serializeFunc.apply(virtualValue);
+    }
 
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public Date toVirtualValue(String physicalValue) {
-		if (physicalValue == null || physicalValue.length() == 0) {
-			return null;
-		}
-		return _deserializeFunc.eval(physicalValue);
-	}
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Date toVirtualValue(String physicalValue) {
+        if (physicalValue == null || physicalValue.length() == 0) {
+            return null;
+        }
+        return _deserializeFunc.apply(physicalValue);
+    }
 
 }
diff --git a/core/src/main/java/org/apache/metamodel/data/AbstractDataSet.java b/core/src/main/java/org/apache/metamodel/data/AbstractDataSet.java
index d296735..f616ddc 100644
--- a/core/src/main/java/org/apache/metamodel/data/AbstractDataSet.java
+++ b/core/src/main/java/org/apache/metamodel/data/AbstractDataSet.java
@@ -22,8 +22,7 @@
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
-
-import javax.swing.table.TableModel;
+import java.util.Objects;
 
 import org.apache.metamodel.MetaModelHelper;
 import org.apache.metamodel.query.SelectItem;
@@ -38,15 +37,6 @@
 
     private final DataSetHeader _header;
 
-    /**
-     * @deprecated use one of the other constructors, to provide header
-     *             information.
-     */
-    @Deprecated
-    public AbstractDataSet() {
-        _header = null;
-    }
-
     public AbstractDataSet(SelectItem[] selectItems) {
         this(Arrays.asList(selectItems));
     }
@@ -71,7 +61,7 @@
     }
 
     public AbstractDataSet(DataSetHeader header) {
-        _header = header;
+        _header = Objects.requireNonNull(header);
     }
 
     public AbstractDataSet(Column[] columns) {
@@ -110,15 +100,6 @@
      * {@inheritDoc}
      */
     @Override
-    public final TableModel toTableModel() {
-        TableModel tableModel = new DataSetTableModel(this);
-        return tableModel;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public final List<Object[]> toObjectArrays() {
         try {
             List<Object[]> objects = new ArrayList<Object[]>();
diff --git a/core/src/main/java/org/apache/metamodel/data/AbstractRow.java b/core/src/main/java/org/apache/metamodel/data/AbstractRow.java
index b736592..9c931f1 100644
--- a/core/src/main/java/org/apache/metamodel/data/AbstractRow.java
+++ b/core/src/main/java/org/apache/metamodel/data/AbstractRow.java
@@ -122,12 +122,6 @@
     }
 
     @Override
-    public Row getSubSelection(final SelectItem[] selectItems) {
-        final DataSetHeader header = new SimpleDataSetHeader(selectItems);
-        return getSubSelection(header);
-    }
-
-    @Override
     public final SelectItem[] getSelectItems() {
         return getHeader().getSelectItems();
     }
diff --git a/core/src/main/java/org/apache/metamodel/data/DataSet.java b/core/src/main/java/org/apache/metamodel/data/DataSet.java
index 9c29860..993d408 100644
--- a/core/src/main/java/org/apache/metamodel/data/DataSet.java
+++ b/core/src/main/java/org/apache/metamodel/data/DataSet.java
@@ -22,8 +22,6 @@
 import java.util.Iterator;
 import java.util.List;
 
-import javax.swing.table.TableModel;
-
 import org.apache.metamodel.query.SelectItem;
 
 /**
@@ -67,14 +65,6 @@
     public void close();
 
     /**
-     * Converts the DataSet into a TableModel (will load all values into memory).
-     * 
-     * @deprecated instantiate a new {@link DataSetTableModel} instead.
-     */
-    @Deprecated
-    public TableModel toTableModel();
-
-    /**
      * Converts the DataSet into a list of object arrays (will load all values
      * into memory)
      */
diff --git a/core/src/main/java/org/apache/metamodel/data/DefaultRow.java b/core/src/main/java/org/apache/metamodel/data/DefaultRow.java
index 0e1fdf7..872b375 100644
--- a/core/src/main/java/org/apache/metamodel/data/DefaultRow.java
+++ b/core/src/main/java/org/apache/metamodel/data/DefaultRow.java
@@ -90,79 +90,6 @@
         this(header, values, null);
     }
 
-    /**
-     * Constructs a row from an array of SelectItems and an array of
-     * corresponding values
-     * 
-     * @param items
-     *            the array of SelectItems
-     * @param values
-     *            the array of values
-     * 
-     * @deprecated use {@link #DefaultRow(DataSetHeader, Object[])} or
-     *             {@link #DefaultRow(DataSetHeader, Object[], Style[])}
-     *             instead.
-     */
-    @Deprecated
-    public DefaultRow(SelectItem[] items, Object[] values) {
-        this(Arrays.asList(items), values, null);
-    }
-
-    /**
-     * Constructs a row from an array of SelectItems and an array of
-     * corresponding values
-     * 
-     * @param items
-     *            the array of SelectItems
-     * @param values
-     *            the array of values
-     * @param styles
-     *            an optional array of styles
-     * @deprecated use {@link #DefaultRow(DataSetHeader, Object[])} or
-     *             {@link #DefaultRow(DataSetHeader, Object[], Style[])}
-     *             instead.
-     */
-    @Deprecated
-    public DefaultRow(SelectItem[] items, Object[] values, Style[] styles) {
-        this(Arrays.asList(items), values, styles);
-    }
-
-    /**
-     * Constructs a row from a list of SelectItems and an array of corresponding
-     * values
-     * 
-     * @param items
-     *            the list of SelectItems
-     * @param values
-     *            the array of values
-     * @deprecated use {@link #DefaultRow(DataSetHeader, Object[])} or
-     *             {@link #DefaultRow(DataSetHeader, Object[], Style[])}
-     *             instead.
-     */
-    @Deprecated
-    public DefaultRow(List<SelectItem> items, Object[] values) {
-        this(items, values, null);
-    }
-
-    /**
-     * Constructs a row from a list of SelectItems and an array of corresponding
-     * values
-     * 
-     * @param items
-     *            the list of SelectItems
-     * @param values
-     *            the array of values
-     * @param styles
-     *            an optional array of styles
-     * @deprecated use {@link #DefaultRow(DataSetHeader, Object[])} or
-     *             {@link #DefaultRow(DataSetHeader, Object[], Style[])}
-     *             instead.
-     */
-    @Deprecated
-    public DefaultRow(List<SelectItem> items, Object[] values, Style[] styles) {
-        this(new SimpleDataSetHeader(items), values, styles);
-    }
-
     @Override
     public Object getValue(int index) throws ArrayIndexOutOfBoundsException {
         return _values[index];
diff --git a/core/src/main/java/org/apache/metamodel/data/Row.java b/core/src/main/java/org/apache/metamodel/data/Row.java
index d636343..65fc273 100644
--- a/core/src/main/java/org/apache/metamodel/data/Row.java
+++ b/core/src/main/java/org/apache/metamodel/data/Row.java
@@ -108,17 +108,6 @@
     /**
      * Creates a row similar to this one but only with a subset of the values.
      * 
-     * @param selectItems
-     *            the select items (~ columns) to sub-select the row with
-     * @return a new Row object containing only the select items requested
-     * @deprecated use {@link #getSubSelection(DataSetHeader)} instead.
-     */
-    @Deprecated
-    public Row getSubSelection(SelectItem[] selectItems);
-
-    /**
-     * Creates a row similar to this one but only with a subset of the values.
-     * 
      * @param header
      *            the new header to sub-select the row with
      * @return a new Row object containing only the select items in the newly
diff --git a/core/src/main/java/org/apache/metamodel/data/UnionDataSet.java b/core/src/main/java/org/apache/metamodel/data/UnionDataSet.java
new file mode 100644
index 0000000..7962f56
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/data/UnionDataSet.java
@@ -0,0 +1,87 @@
+/**
+ * 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.data;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import org.apache.metamodel.query.InvokableQuery;
+import org.apache.metamodel.util.ImmutableRef;
+
+/**
+ * A {@link DataSet} that represents the union of two or more other data sets
+ */
+public class UnionDataSet extends AbstractDataSet implements WrappingDataSet {
+
+    private final Iterable<Supplier<DataSet>> _dataSetProviders;
+    private Iterator<Supplier<DataSet>> _iterator;
+    private DataSet _currentDataSet;
+
+    public static DataSet ofQueries(DataSetHeader header, Collection<InvokableQuery> queries) {
+        final Function<InvokableQuery, Supplier<DataSet>> mapper = q -> {
+            return () -> {
+                return q.execute();
+            };
+        };
+        return new UnionDataSet(header, queries.stream().map(mapper).collect(Collectors.toList()));
+    }
+
+    public static DataSet ofDataSets(DataSetHeader header, Collection<DataSet> dataSets) {
+        return new UnionDataSet(header, dataSets.stream().map(ds -> ImmutableRef.of(ds)).collect(Collectors.toList()));
+    }
+
+    private UnionDataSet(DataSetHeader header, Iterable<Supplier<DataSet>> dataSetProviders) {
+        super(header);
+        _dataSetProviders = Objects.requireNonNull(dataSetProviders);
+    }
+
+    @Override
+    public boolean next() {
+        if (_iterator == null) {
+            _iterator = _dataSetProviders.iterator();
+        }
+
+        while (_currentDataSet == null || !_currentDataSet.next()) {
+            if (!_iterator.hasNext()) {
+                _currentDataSet = null;
+                return false;
+            }
+            _currentDataSet = _iterator.next().get();
+            assert getHeader().size() == _currentDataSet.getSelectItems().length;
+        }
+        return true;
+    }
+
+    @Override
+    public Row getRow() {
+        if (_currentDataSet == null) {
+            return null;
+        }
+        return _currentDataSet.getRow();
+    }
+
+    @Override
+    public DataSet getWrappedDataSet() {
+        return _currentDataSet;
+    }
+}
diff --git a/core/src/main/java/org/apache/metamodel/intercept/InterceptableDataContext.java b/core/src/main/java/org/apache/metamodel/intercept/InterceptableDataContext.java
index a356b9a..f8c74cb 100644
--- a/core/src/main/java/org/apache/metamodel/intercept/InterceptableDataContext.java
+++ b/core/src/main/java/org/apache/metamodel/intercept/InterceptableDataContext.java
@@ -21,6 +21,7 @@
 import org.apache.metamodel.DataContext;
 import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.create.TableCreationBuilder;
 import org.apache.metamodel.data.DataSet;
@@ -206,7 +207,7 @@
         Schema[] schemas = getSchemas();
         String[] schemaNames = new String[schemas.length];
         for (int i = 0; i < schemaNames.length; i++) {
-            schemaNames[i] = new HasNameMapper().eval(schemas[i]);
+            schemaNames[i] = new HasNameMapper().apply(schemas[i]);
         }
         return schemaNames;
     }
@@ -241,7 +242,7 @@
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
+    public UpdateSummary executeUpdate(UpdateScript update) {
         if (!(_delegate instanceof UpdateableDataContext)) {
             throw new UnsupportedOperationException("Delegate is not an UpdateableDataContext");
         }
@@ -250,14 +251,13 @@
         if (_tableCreationInterceptors.isEmpty() && _tableDropInterceptors.isEmpty()
                 && _rowInsertionInterceptors.isEmpty() && _rowUpdationInterceptors.isEmpty()
                 && _rowDeletionInterceptors.isEmpty()) {
-            delegate.executeUpdate(update);
-            return;
+            return delegate.executeUpdate(update);
         }
 
-        UpdateScript interceptableUpdateScript = new InterceptableUpdateScript(this, update,
+        final UpdateScript interceptableUpdateScript = new InterceptableUpdateScript(this, update,
                 _tableCreationInterceptors, _tableDropInterceptors, _rowInsertionInterceptors,
                 _rowUpdationInterceptors, _rowDeletionInterceptors);
-        delegate.executeUpdate(interceptableUpdateScript);
+        return delegate.executeUpdate(interceptableUpdateScript);
     }
 
     @Override
diff --git a/core/src/main/java/org/apache/metamodel/query/AbstractQueryClause.java b/core/src/main/java/org/apache/metamodel/query/AbstractQueryClause.java
index 572d69f..6f2e198 100644
--- a/core/src/main/java/org/apache/metamodel/query/AbstractQueryClause.java
+++ b/core/src/main/java/org/apache/metamodel/query/AbstractQueryClause.java
@@ -57,13 +57,13 @@
     }
 
     @Override
-    public QueryClause<E> setItems(E... items) {
+    public QueryClause<E> setItems(@SuppressWarnings("unchecked") E... items) {
         _items.clear();
         return addItems(items);
     }
 
     @Override
-    public QueryClause<E> addItems(E... items) {
+    public QueryClause<E> addItems(@SuppressWarnings("unchecked") E... items) {
         for (E item : items) {
             addItem(item);
         }
@@ -95,7 +95,7 @@
     public int getItemCount() {
         return _items.size();
     }
-    
+
     @Override
     public int indexOf(E item) {
         return _items.indexOf(item);
diff --git a/core/src/main/java/org/apache/metamodel/query/DefaultInvokableQuery.java b/core/src/main/java/org/apache/metamodel/query/DefaultInvokableQuery.java
new file mode 100644
index 0000000..368ce2b
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/DefaultInvokableQuery.java
@@ -0,0 +1,53 @@
+/**
+ * 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.Objects;
+
+import org.apache.metamodel.DataContext;
+import org.apache.metamodel.data.DataSet;
+
+/**
+ * Default implementation of {@link InvokableQuery}, based on a ready to go {@link Query} and it's {@link DataContext}.
+ */
+final class DefaultInvokableQuery implements InvokableQuery {
+
+    private final Query _query;
+    private final DataContext _dataContext;
+
+    public DefaultInvokableQuery(Query query, DataContext dataContext) {
+        _query = Objects.requireNonNull(query);
+        _dataContext = Objects.requireNonNull(dataContext);
+    }
+
+    @Override
+    public CompiledQuery compile() {
+        return _dataContext.compileQuery(_query);
+    }
+
+    @Override
+    public DataSet execute() {
+        return _dataContext.executeQuery(_query);
+    }
+
+    @Override
+    public String toString() {
+        return "DefaultInvokableQuery[" + _query + "]";
+    }
+}
diff --git a/core/src/main/java/org/apache/metamodel/query/FilterItem.java b/core/src/main/java/org/apache/metamodel/query/FilterItem.java
index 18e44cf..427844b 100644
--- a/core/src/main/java/org/apache/metamodel/query/FilterItem.java
+++ b/core/src/main/java/org/apache/metamodel/query/FilterItem.java
@@ -466,27 +466,6 @@
     }
 
     /**
-     * Gets the {@link FilterItem}s that this filter item consists of, if it is
-     * a compound filter item.
-     *
-     * @deprecated use {@link #getChildItems()} instead
-     */
-    @Deprecated
-    public FilterItem[] getOrItems() {
-        return getChildItems();
-    }
-
-    /**
-     * Gets the number of child items, if this is a compound filter item.
-     *
-     * @deprecated use {@link #getChildItemCount()} instead.
-     */
-    @Deprecated
-    public int getOrItemCount() {
-        return getChildItemCount();
-    }
-
-    /**
      * Get the number of child items, if this is a compound filter item.
      */
     public int getChildItemCount() {
diff --git a/core/src/main/java/org/apache/metamodel/query/InvokableQuery.java b/core/src/main/java/org/apache/metamodel/query/InvokableQuery.java
new file mode 100644
index 0000000..d7770ff
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/InvokableQuery.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.DataContext;
+import org.apache.metamodel.data.DataSet;
+
+/**
+ * Represents a {@link Query} or query-builder object that's aware of it's {@link DataContext} and is ready to execute
+ * or compile.
+ */
+public interface InvokableQuery {
+
+    /**
+     * Compiles the query
+     * 
+     * @return the {@link CompiledQuery} that is is returned by compiling the query.
+     */
+    public CompiledQuery compile();
+
+    /**
+     * Executes the query.
+     * 
+     * @return the {@link DataSet} that is returned by executing the query.
+     */
+    public DataSet execute();
+}
diff --git a/core/src/main/java/org/apache/metamodel/query/OrderByItem.java b/core/src/main/java/org/apache/metamodel/query/OrderByItem.java
index 3fde53c..c0a7682 100644
--- a/core/src/main/java/org/apache/metamodel/query/OrderByItem.java
+++ b/core/src/main/java/org/apache/metamodel/query/OrderByItem.java
@@ -57,26 +57,6 @@
 	}
 
 	/**
-	 * Creates an OrderByItem
-	 * 
-	 * @param selectItem
-	 * @param ascending
-	 * @deprecated user OrderByItem(SelectItem, Direction) instead
-	 */
-	@Deprecated
-	public OrderByItem(SelectItem selectItem, boolean ascending) {
-		if (selectItem == null) {
-			throw new IllegalArgumentException("SelectItem cannot be null");
-		}
-		_selectItem = selectItem;
-		if (ascending) {
-			_direction = Direction.ASC;
-		} else {
-			_direction = Direction.DESC;
-		}
-	}
-
-	/**
 	 * Creates an ascending OrderByItem
 	 * 
 	 * @param selectItem
diff --git a/core/src/main/java/org/apache/metamodel/query/Query.java b/core/src/main/java/org/apache/metamodel/query/Query.java
index f8194a7..7dc9278 100644
--- a/core/src/main/java/org/apache/metamodel/query/Query.java
+++ b/core/src/main/java/org/apache/metamodel/query/Query.java
@@ -271,18 +271,6 @@
         return orderBy(column, Direction.ASC);
     }
 
-    /**
-     * @deprecated use orderBy(Column, Direction) instead
-     */
-    @Deprecated
-    public Query orderBy(Column column, boolean ascending) {
-        if (ascending) {
-            return orderBy(column, Direction.ASC);
-        } else {
-            return orderBy(column, Direction.DESC);
-        }
-    }
-
     public Query orderBy(Column column, Direction direction) {
         SelectItem selectItem = _selectClause.getSelectItem(column);
         if (selectItem == null) {
@@ -581,6 +569,10 @@
     public Integer getFirstRow() {
         return _firstRow;
     }
+    
+    public InvokableQuery invokable(DataContext dataContext) {
+        return new DefaultInvokableQuery(this, dataContext);
+    }
 
     @Override
     protected void decorateIdentity(List<Object> identifiers) {
diff --git a/core/src/main/java/org/apache/metamodel/query/QueryClause.java b/core/src/main/java/org/apache/metamodel/query/QueryClause.java
index 19a9472..b87d141 100644
--- a/core/src/main/java/org/apache/metamodel/query/QueryClause.java
+++ b/core/src/main/java/org/apache/metamodel/query/QueryClause.java
@@ -23,33 +23,33 @@
 
 public interface QueryClause<E> extends Serializable {
 
-	public QueryClause<E> setItems(E... items);
+    public QueryClause<E> setItems(@SuppressWarnings("unchecked") E... items);
 
-	public QueryClause<E> addItems(E... items);
+    public QueryClause<E> addItems(@SuppressWarnings("unchecked") E... items);
 
-	public QueryClause<E> addItems(Iterable<E> items);
+    public QueryClause<E> addItems(Iterable<E> items);
 
-	public QueryClause<E> addItem(int index, E item);
-	
-	public QueryClause<E> addItem(E item);
-	
-	public boolean isEmpty();
+    public QueryClause<E> addItem(int index, E item);
 
-	public int getItemCount();
+    public QueryClause<E> addItem(E item);
 
-	public E getItem(int index);
+    public boolean isEmpty();
 
-	public List<E> getItems();
+    public int getItemCount();
 
-	public QueryClause<E> removeItem(int index);
+    public E getItem(int index);
 
-	public QueryClause<E> removeItem(E item);
+    public List<E> getItems();
 
-	public QueryClause<E> removeItems();
-	
-	public String toSql(boolean includeSchemaInColumnPaths);
+    public QueryClause<E> removeItem(int index);
 
-	public String toSql();
-	
-	public int indexOf(E item);
+    public QueryClause<E> removeItem(E item);
+
+    public QueryClause<E> removeItems();
+
+    public String toSql(boolean includeSchemaInColumnPaths);
+
+    public String toSql();
+
+    public int indexOf(E item);
 }
diff --git a/core/src/main/java/org/apache/metamodel/query/SelectItem.java b/core/src/main/java/org/apache/metamodel/query/SelectItem.java
index bc872d1..df4b995 100644
--- a/core/src/main/java/org/apache/metamodel/query/SelectItem.java
+++ b/core/src/main/java/org/apache/metamodel/query/SelectItem.java
@@ -98,7 +98,7 @@
     }
 
     public static boolean isCountAllItem(SelectItem item) {
-        if (item != null && item.getFunction() != null && item.getFunction().toString().equals("COUNT")
+        if (item != null && item.getAggregateFunction() != null && item.getAggregateFunction().toString().equals("COUNT")
                 && item.getExpression() == "*") {
             return true;
         }
@@ -242,19 +242,6 @@
         return this;
     }
 
-    /**
-     * 
-     * @return
-     * @deprecated use {@link #getAggregateFunction()} or
-     *             {@link #getScalarFunction()} instead,
-     *             or {@link #hasFunction()} to check if a
-     *             function is set at all.
-     */
-    @Deprecated
-    public FunctionType getFunction() {
-        return _function;
-    }
-
     public boolean hasFunction(){
         return _function != null;
     }
@@ -349,14 +336,6 @@
         return _subQuerySelectItem;
     }
 
-    /**
-     * @deprecated use {@link #getFromItem()} instead
-     */
-    @Deprecated
-    public FromItem getSubQueryFromItem() {
-        return _fromItem;
-    }
-
     public FromItem getFromItem() {
         return _fromItem;
     }
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/AbstractFilterBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/AbstractFilterBuilder.java
index 2cf91ef..9f95ef7 100644
--- a/core/src/main/java/org/apache/metamodel/query/builder/AbstractFilterBuilder.java
+++ b/core/src/main/java/org/apache/metamodel/query/builder/AbstractFilterBuilder.java
@@ -208,12 +208,6 @@
         throw new UnsupportedOperationException("Argument must be a Boolean, Number, Date or String. Found: " + obj);
     }
 
-    @Deprecated
-    @Override
-    public B higherThan(Column arg) {
-        return greaterThan(arg);
-    }
-
     @Override
     public B greaterThan(Column column) {
         if (column == null) {
@@ -222,12 +216,6 @@
         return applyFilter(new FilterItem(_selectItem, OperatorType.GREATER_THAN, new SelectItem(column)));
     }
 
-    @Deprecated
-    @Override
-    public B higherThan(Date arg) {
-        return greaterThan(arg);
-    }
-
     @Override
     public B greaterThan(Date date) {
         if (date == null) {
@@ -236,12 +224,6 @@
         return applyFilter(new FilterItem(_selectItem, OperatorType.GREATER_THAN, date));
     }
 
-    @Deprecated
-    @Override
-    public B higherThan(Number arg) {
-        return greaterThan(arg);
-    }
-
     @Override
     public B greaterThan(Number number) {
         if (number == null) {
@@ -250,12 +232,6 @@
         return applyFilter(new FilterItem(_selectItem, OperatorType.GREATER_THAN, number));
     }
 
-    @Deprecated
-    @Override
-    public B higherThan(String arg) {
-        return greaterThan(arg);
-    }
-
     @Override
     public B greaterThan(String string) {
         if (string == null) {
@@ -581,36 +557,6 @@
     }
 
     @Override
-    @Deprecated
-    public B equals(Boolean bool) {
-        return isEquals(bool);
-    }
-
-    @Override
-    @Deprecated
-    public B equals(Column column) {
-        return isEquals(column);
-    }
-
-    @Override
-    @Deprecated
-    public B equals(Date date) {
-        return isEquals(date);
-    }
-
-    @Override
-    @Deprecated
-    public B equals(Number number) {
-        return isEquals(number);
-    }
-
-    @Override
-    @Deprecated
-    public B equals(String string) {
-        return isEquals(string);
-    }
-
-    @Override
     public B lt(Object obj) {
         return lessThan(obj);
     }
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/AbstractQueryFilterBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/AbstractQueryFilterBuilder.java
index 6a0c900..08e3003 100644
--- a/core/src/main/java/org/apache/metamodel/query/builder/AbstractQueryFilterBuilder.java
+++ b/core/src/main/java/org/apache/metamodel/query/builder/AbstractQueryFilterBuilder.java
@@ -142,12 +142,6 @@
         return _filterBuilder.differentFrom(obj);
     }
 
-    @Deprecated
-    @Override
-    public B higherThan(Column arg) {
-        return _filterBuilder.higherThan(arg);
-    }
-
     public B greaterThan(Column column) {
         return _filterBuilder.greaterThan(column);
     }
@@ -157,34 +151,16 @@
         return _filterBuilder.greaterThan(obj);
     }
 
-    @Deprecated
-    @Override
-    public B higherThan(Date arg) {
-        return _filterBuilder.higherThan(arg);
-    }
-
     @Override
     public B greaterThan(Date date) {
         return _filterBuilder.greaterThan(date);
     }
 
-    @Deprecated
-    @Override
-    public B higherThan(Number arg) {
-        return _filterBuilder.higherThan(arg);
-    }
-
     @Override
     public B greaterThan(Number number) {
         return _filterBuilder.greaterThan(number);
     }
 
-    @Deprecated
-    @Override
-    public B higherThan(String arg) {
-        return _filterBuilder.higherThan(arg);
-    }
-
     @Override
     public B greaterThan(String string) {
         return _filterBuilder.greaterThan(string);
@@ -423,36 +399,6 @@
     }
 
     @Override
-    @Deprecated
-    public B equals(Boolean bool) {
-        return isEquals(bool);
-    }
-
-    @Override
-    @Deprecated
-    public B equals(Column column) {
-        return isEquals(column);
-    }
-
-    @Override
-    @Deprecated
-    public B equals(Date date) {
-        return isEquals(date);
-    }
-
-    @Override
-    @Deprecated
-    public B equals(Number number) {
-        return isEquals(number);
-    }
-
-    @Override
-    @Deprecated
-    public B equals(String string) {
-        return isEquals(string);
-    }
-
-    @Override
     public B lt(Object obj) {
         return lessThan(obj);
     }
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/FilterBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/FilterBuilder.java
index a6cf57b..0ff7b17 100644
--- a/core/src/main/java/org/apache/metamodel/query/builder/FilterBuilder.java
+++ b/core/src/main/java/org/apache/metamodel/query/builder/FilterBuilder.java
@@ -146,46 +146,6 @@
     public B isEquals(Object obj);
 
     /**
-     * Equal to ...
-     *
-     * @deprecated use 'eq' or 'isEquals' instead.
-     */
-    @Deprecated
-    public B equals(Column column);
-
-    /**
-     * Equal to ...
-     *
-     * @deprecated use 'eq' or 'isEquals' instead.
-     */
-    @Deprecated
-    public B equals(Date date);
-
-    /**
-     * Equal to ...
-     *
-     * @deprecated use 'eq' or 'isEquals' instead.
-     */
-    @Deprecated
-    public B equals(Number number);
-
-    /**
-     * Equal to ...
-     *
-     * @deprecated use 'eq' or 'isEquals' instead.
-     */
-    @Deprecated
-    public B equals(String string);
-
-    /**
-     * Equal to ...
-     *
-     * @deprecated use 'eq' or 'isEquals' instead.
-     */
-    @Deprecated
-    public B equals(Boolean bool);
-
-    /**
      * Not equal to ...
      */
     public B differentFrom(Column column);
@@ -247,14 +207,6 @@
 
     /**
      * Greater than ...
-     *
-     * @deprecated use {@link #greaterThan(Column)} instead
-     */
-    @Deprecated
-    public B higherThan(Column column);
-
-    /**
-     * Greater than ...
      */
     public B greaterThan(Column column);
 
@@ -275,14 +227,6 @@
 
     /**
      * Greater than ...
-     *
-     * @deprecated use {@link #greaterThan(Date)} instead
-     */
-    @Deprecated
-    public B higherThan(Date date);
-
-    /**
-     * Greater than ...
      */
     public B greaterThan(Date date);
 
@@ -292,12 +236,6 @@
     public B gt(Date date);
 
     /**
-     * @deprecated use {@link #greaterThan(Number)} instead
-     */
-    @Deprecated
-    public B higherThan(Number number);
-
-    /**
      * Greater than ...
      */
     public B greaterThan(Number number);
@@ -309,14 +247,6 @@
 
     /**
      * Greater than ...
-     *
-     * @deprecated use {@link #greaterThan(String)} instead
-     */
-    @Deprecated
-    public B higherThan(String string);
-
-    /**
-     * Greater than ...
      */
     public B greaterThan(String string);
 
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java
index f94ebdb..f425221 100644
--- a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java
+++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java
@@ -18,12 +18,10 @@
  */
 package org.apache.metamodel.query.builder;
 
-import org.apache.metamodel.DataContext;
-import org.apache.metamodel.data.DataSet;
-import org.apache.metamodel.query.CompiledQuery;
 import org.apache.metamodel.query.FilterItem;
 import org.apache.metamodel.query.FunctionType;
 import org.apache.metamodel.query.Query;
+import org.apache.metamodel.query.InvokableQuery;
 import org.apache.metamodel.query.ScalarFunction;
 import org.apache.metamodel.schema.Column;
 
@@ -33,7 +31,7 @@
  * 
  * @param <B>
  */
-public interface SatisfiedQueryBuilder<B extends SatisfiedQueryBuilder<?>> {
+public interface SatisfiedQueryBuilder<B extends SatisfiedQueryBuilder<?>> extends InvokableQuery {
 
     public ColumnSelectBuilder<B> select(Column column);
 
@@ -119,16 +117,6 @@
      */
     public Query toQuery();
 
-    public CompiledQuery compile();
-
-    /**
-     * Executes the built query. This call is similar to calling
-     * {@link #toQuery()} and then {@link DataContext#executeQuery(Query)}.
-     * 
-     * @return the {@link DataSet} that is returned by executing the query.
-     */
-    public DataSet execute();
-
     /**
      * Finds a column by name within the already defined FROM items
      * 
diff --git a/core/src/main/java/org/apache/metamodel/schema/AbstractSchema.java b/core/src/main/java/org/apache/metamodel/schema/AbstractSchema.java
index a69382d..e44737a 100644
--- a/core/src/main/java/org/apache/metamodel/schema/AbstractSchema.java
+++ b/core/src/main/java/org/apache/metamodel/schema/AbstractSchema.java
@@ -23,11 +23,9 @@
 import java.util.List;
 import java.util.Set;
 
-import org.apache.metamodel.util.Action;
 import org.apache.metamodel.util.CollectionUtils;
 import org.apache.metamodel.util.EqualsBuilder;
 import org.apache.metamodel.util.HasNameMapper;
-import org.apache.metamodel.util.Predicate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -53,14 +51,11 @@
     @Override
     public Relationship[] getRelationships() {
         final Set<Relationship> result = new LinkedHashSet<Relationship>();
-        CollectionUtils.forEach(getTables(), new Action<Table>() {
-            @Override
-            public void run(Table table) {
-                Relationship[] relations = table.getRelationships();
-                for (int i = 0; i < relations.length; i++) {
-                    Relationship relation = relations[i];
-                    result.add(relation);
-                }
+        CollectionUtils.forEach(getTables(), table -> {
+            final Relationship[] relations = table.getRelationships();
+            for (int i = 0; i < relations.length; i++) {
+                final Relationship relation = relations[i];
+                result.add(relation);
             }
         });
         return result.toArray(new Relationship[result.size()]);
@@ -94,11 +89,8 @@
 
     @Override
     public final Table[] getTables(final TableType type) {
-        return CollectionUtils.filter(getTables(), new Predicate<Table>() {
-            @Override
-            public Boolean eval(Table table) {
-                return table.getType() == type;
-            }
+        return CollectionUtils.filter(getTables(), table -> {
+            return table.getType() == type;
         }).toArray(new Table[0]);
     }
 
@@ -148,7 +140,7 @@
     public final String toString() {
         return "Schema[name=" + getName() + "]";
     }
-    
+
     @Override
     public boolean equals(Object obj) {
         if (obj == null) {
@@ -168,14 +160,15 @@
                     int tableCount2 = other.getTableCount();
                     eb.append(tableCount1, tableCount2);
                 } catch (Exception e) {
-                    // might occur when schemas are disconnected. Omit this check then.
+                    // might occur when schemas are disconnected. Omit this
+                    // check then.
                 }
             }
             return eb.isEquals();
         }
         return false;
     }
-    
+
     @Override
     public int hashCode() {
         String name = getName();
diff --git a/core/src/main/java/org/apache/metamodel/schema/AbstractTable.java b/core/src/main/java/org/apache/metamodel/schema/AbstractTable.java
index 7af3656..4f5ad7f 100644
--- a/core/src/main/java/org/apache/metamodel/schema/AbstractTable.java
+++ b/core/src/main/java/org/apache/metamodel/schema/AbstractTable.java
@@ -23,12 +23,11 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Predicate;
 
 import org.apache.metamodel.MetaModelHelper;
-import org.apache.metamodel.util.Action;
 import org.apache.metamodel.util.CollectionUtils;
 import org.apache.metamodel.util.HasNameMapper;
-import org.apache.metamodel.util.Predicate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -101,7 +100,7 @@
     public final Column[] getNumberColumns() {
         return CollectionUtils.filter(getColumns(), new Predicate<Column>() {
             @Override
-            public Boolean eval(Column col) {
+            public boolean test(Column col) {
                 ColumnType type = col.getType();
                 return type != null && type.isNumber();
             }
@@ -112,7 +111,7 @@
     public final Column[] getLiteralColumns() {
         return CollectionUtils.filter(getColumns(), new Predicate<Column>() {
             @Override
-            public Boolean eval(Column col) {
+            public boolean test(Column col) {
                 ColumnType type = col.getType();
                 return type != null && type.isLiteral();
             }
@@ -121,53 +120,36 @@
 
     @Override
     public final Column[] getTimeBasedColumns() {
-        return CollectionUtils.filter(getColumns(), new Predicate<Column>() {
-            @Override
-            public Boolean eval(Column col) {
-                ColumnType type = col.getType();
-                return type != null && type.isTimeBased();
-            }
+        return CollectionUtils.filter(getColumns(), col -> {
+            final ColumnType type = col.getType();
+            return type != null && type.isTimeBased();
         }).toArray(new Column[0]);
     }
 
     @Override
     public final Column[] getBooleanColumns() {
-        return CollectionUtils.filter(getColumns(), new Predicate<Column>() {
-            @Override
-            public Boolean eval(Column col) {
-                ColumnType type = col.getType();
-                return type != null && type.isBoolean();
-            }
+        return CollectionUtils.filter(getColumns(), col -> {
+            final ColumnType type = col.getType();
+            return type != null && type.isBoolean();
         }).toArray(new Column[0]);
     }
 
     @Override
     public final Column[] getIndexedColumns() {
-        return CollectionUtils.filter(getColumns(), new Predicate<Column>() {
-            @Override
-            public Boolean eval(Column col) {
-                return col.isIndexed();
-            }
-        }).toArray(new Column[0]);
+        return CollectionUtils.filter(getColumns(), Column::isIndexed).toArray(new Column[0]);
     }
 
     @Override
     public final Relationship[] getForeignKeyRelationships() {
-        return CollectionUtils.filter(getRelationships(), new Predicate<Relationship>() {
-            @Override
-            public Boolean eval(Relationship arg) {
-                return AbstractTable.this.equals(arg.getForeignTable());
-            }
+        return CollectionUtils.filter(getRelationships(), rel -> {
+            return AbstractTable.this.equals(rel.getForeignTable());
         }).toArray(new Relationship[0]);
     }
 
     @Override
     public final Relationship[] getPrimaryKeyRelationships() {
-        return CollectionUtils.filter(getRelationships(), new Predicate<Relationship>() {
-            @Override
-            public Boolean eval(Relationship arg) {
-                return AbstractTable.this.equals(arg.getPrimaryTable());
-            }
+        return CollectionUtils.filter(getRelationships(), rel -> {
+            return AbstractTable.this.equals(rel.getPrimaryTable());
         }).toArray(new Relationship[0]);
     }
 
@@ -175,13 +157,10 @@
     public final Column[] getForeignKeys() {
         final Set<Column> columns = new HashSet<Column>();
         final Relationship[] relationships = getForeignKeyRelationships();
-        CollectionUtils.forEach(relationships, new Action<Relationship>() {
-            @Override
-            public void run(Relationship arg) {
-                Column[] foreignColumns = arg.getForeignColumns();
-                for (Column column : foreignColumns) {
-                    columns.add(column);
-                }
+        CollectionUtils.forEach(relationships, rel -> {
+            Column[] foreignColumns = rel.getForeignColumns();
+            for (Column column : foreignColumns) {
+                columns.add(column);
             }
         });
         return columns.toArray(new Column[columns.size()]);
@@ -221,16 +200,13 @@
     public final Relationship[] getRelationships(final Table otherTable) {
         Relationship[] relationships = getRelationships();
 
-        return CollectionUtils.filter(relationships, new Predicate<Relationship>() {
-            @Override
-            public Boolean eval(Relationship relation) {
-                if (relation.getForeignTable() == otherTable && relation.getPrimaryTable() == AbstractTable.this) {
-                    return true;
-                } else if (relation.getForeignTable() == AbstractTable.this && relation.getPrimaryTable() == otherTable) {
-                    return true;
-                }
-                return false;
+        return CollectionUtils.filter(relationships, relation -> {
+            if (relation.getForeignTable() == otherTable && relation.getPrimaryTable() == AbstractTable.this) {
+                return true;
+            } else if (relation.getForeignTable() == AbstractTable.this && relation.getPrimaryTable() == otherTable) {
+                return true;
             }
+            return false;
         }).toArray(new Relationship[0]);
     }
 
diff --git a/core/src/main/java/org/apache/metamodel/util/AbstractResource.java b/core/src/main/java/org/apache/metamodel/util/AbstractResource.java
index 7f96973..fcc2628 100644
--- a/core/src/main/java/org/apache/metamodel/util/AbstractResource.java
+++ b/core/src/main/java/org/apache/metamodel/util/AbstractResource.java
@@ -20,6 +20,7 @@
 
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.function.Function;
 
 /**
  * Abstract implementation of many methods in {@link Resource}
@@ -38,12 +39,25 @@
             FileHelper.safeClose(in);
         }
     }
-
+    
     @Override
-    public final <E> E read(Func<InputStream, E> readCallback) {
+    public <E> E read(Function<InputStream, E> readCallback) throws ResourceException {
         final InputStream in = read();
         try {
-            final E result = readCallback.eval(in);
+            final E result = readCallback.apply(in);
+            return result;
+        } catch (Exception e) {
+            throw new ResourceException(this, "Error occurred in read callback", e);
+        } finally {
+            FileHelper.safeClose(in);
+        }
+    }
+
+    @Override
+    public final <E> E read(UncheckedFunc<InputStream, E> readCallback) {
+        final InputStream in = read();
+        try {
+            final E result = readCallback.applyUnchecked(in);
             return result;
         } catch (Exception e) {
             throw new ResourceException(this, "Error occurred in read callback", e);
diff --git a/core/src/main/java/org/apache/metamodel/util/Action.java b/core/src/main/java/org/apache/metamodel/util/Action.java
index b602302..2dcb767 100644
--- a/core/src/main/java/org/apache/metamodel/util/Action.java
+++ b/core/src/main/java/org/apache/metamodel/util/Action.java
@@ -18,15 +18,32 @@
  */
 package org.apache.metamodel.util;
 
+import java.util.function.Consumer;
+
 /**
  * Represents an abstract action, which is an executable piece of functionality
- * that takes an argument. An {@link Action} has no return type, unlike a
- * {@link Func}.
+ * that takes an argument. An action is very similar to a {@link Consumer},
+ * except that it allows for throwing exceptions, making it more appropriate for
+ * encapsulating code blocks that may fail.
  * 
  * @param <E>
  *            the argument type of the action
  */
-public interface Action<E> {
+@FunctionalInterface
+public interface Action<E> extends Consumer<E> {
 
-	public void run(E arg) throws Exception;
+    @Override
+    default void accept(E t) {
+        // delegate to run method and propagate exceptions if needed
+        try {
+            run(t);
+        } catch (Exception e) {
+            if (e instanceof RuntimeException) {
+                throw (RuntimeException) e;
+            }
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void run(E arg) throws Exception;
 }
diff --git a/core/src/main/java/org/apache/metamodel/util/CollectionUtils.java b/core/src/main/java/org/apache/metamodel/util/CollectionUtils.java
index 2cd4e6a..5246a3a 100644
--- a/core/src/main/java/org/apache/metamodel/util/CollectionUtils.java
+++ b/core/src/main/java/org/apache/metamodel/util/CollectionUtils.java
@@ -26,6 +26,8 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
 
 /**
  * Various utility methods for handling of collections and arrays.
@@ -260,41 +262,41 @@
         return (E[]) result;
     }
 
-    public static <E> List<E> filter(E[] items, Predicate<? super E> predicate) {
+    public static <E> List<E> filter(E[] items, java.util.function.Predicate<? super E> predicate) {
         return filter(Arrays.asList(items), predicate);
     }
 
-    public static <E> List<E> filter(Iterable<E> items, Predicate<? super E> predicate) {
+    public static <E> List<E> filter(Iterable<E> items, java.util.function.Predicate<? super E> predicate) {
         List<E> result = new ArrayList<E>();
         for (E e : items) {
-            if (predicate.eval(e).booleanValue()) {
+            if (predicate.test(e)) {
                 result.add(e);
             }
         }
         return result;
     }
 
-    public static <I, O> List<O> map(I[] items, Func<? super I, O> func) {
+    public static <I, O> List<O> map(I[] items, Function<? super I, O> func) {
         return map(Arrays.asList(items), func);
     }
 
-    public static <I, O> List<O> map(Iterable<I> items, Func<? super I, O> func) {
+    public static <I, O> List<O> map(Iterable<I> items, Function<? super I, O> func) {
         List<O> result = new ArrayList<O>();
         for (I item : items) {
-            O output = func.eval(item);
+            O output = func.apply(item);
             result.add(output);
         }
         return result;
     }
 
-    public static <E> void forEach(E[] items, Action<? super E> action) {
+    public static <E> void forEach(E[] items, Consumer<? super E> action) {
         forEach(Arrays.asList(items), action);
     }
 
-    public static <E> void forEach(Iterable<E> items, Action<? super E> action) {
+    public static <E> void forEach(Iterable<E> items, Consumer<? super E> action) {
         for (E item : items) {
             try {
-                action.run(item);
+                action.accept(item);
             } catch (Exception e) {
                 if (e instanceof RuntimeException) {
                     throw (RuntimeException) e;
diff --git a/core/src/main/java/org/apache/metamodel/util/ConstantFunc.java b/core/src/main/java/org/apache/metamodel/util/ConstantFunc.java
index 9a48516..639b421 100644
--- a/core/src/main/java/org/apache/metamodel/util/ConstantFunc.java
+++ b/core/src/main/java/org/apache/metamodel/util/ConstantFunc.java
@@ -18,13 +18,15 @@
  */
 package org.apache.metamodel.util;
 
+import java.util.function.Function;
+
 /**
  * A function that always returns the same constant response.
  * 
  * @param <I>
  * @param <O>
  */
-public final class ConstantFunc<I, O> implements Func<I, O> {
+public final class ConstantFunc<I, O> implements Function<I, O> {
 
     private final O _response;
 
@@ -33,7 +35,7 @@
     }
 
     @Override
-    public O eval(I arg) {
+    public O apply(I arg) {
         return _response;
     }
 
diff --git a/core/src/main/java/org/apache/metamodel/util/ExclusionPredicate.java b/core/src/main/java/org/apache/metamodel/util/ExclusionPredicate.java
index aec67c6..c3a8bfe 100644
--- a/core/src/main/java/org/apache/metamodel/util/ExclusionPredicate.java
+++ b/core/src/main/java/org/apache/metamodel/util/ExclusionPredicate.java
@@ -27,7 +27,7 @@
  * 
  * @param <E>
  */
-public class ExclusionPredicate<E> implements Predicate<E> {
+public class ExclusionPredicate<E> implements java.util.function.Predicate<E> {
 
     private final Collection<E> _exclusionList;
 
@@ -36,7 +36,7 @@
     }
 
     @Override
-    public Boolean eval(E arg) {
+    public boolean test(E arg) {
         if (_exclusionList.contains(arg)) {
             return false;
         }
diff --git a/core/src/main/java/org/apache/metamodel/util/FalsePredicate.java b/core/src/main/java/org/apache/metamodel/util/FalsePredicate.java
index f1f4a8e..1b58069 100644
--- a/core/src/main/java/org/apache/metamodel/util/FalsePredicate.java
+++ b/core/src/main/java/org/apache/metamodel/util/FalsePredicate.java
@@ -25,12 +25,12 @@
  * 
  * @param <E>
  */
-public final class FalsePredicate<E> implements Predicate<E>, Serializable {
+public final class FalsePredicate<E> implements java.util.function.Predicate<E>, Serializable {
 
     private static final long serialVersionUID = 1L;
 
     @Override
-    public Boolean eval(E arg) {
+    public boolean test(E arg) {
         return false;
     }
 
diff --git a/core/src/main/java/org/apache/metamodel/util/FileHelper.java b/core/src/main/java/org/apache/metamodel/util/FileHelper.java
index 7465fd0..c955ec6 100644
--- a/core/src/main/java/org/apache/metamodel/util/FileHelper.java
+++ b/core/src/main/java/org/apache/metamodel/util/FileHelper.java
@@ -147,7 +147,6 @@
                 int unread;
 
                 // auto-detect byte-order-mark
-                @SuppressWarnings("resource")
                 final PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream, bom.length);
                 final int n = pushbackInputStream.read(bom, 0, bom.length);
 
diff --git a/core/src/main/java/org/apache/metamodel/util/Func.java b/core/src/main/java/org/apache/metamodel/util/Func.java
index 44014e0..687189a 100644
--- a/core/src/main/java/org/apache/metamodel/util/Func.java
+++ b/core/src/main/java/org/apache/metamodel/util/Func.java
@@ -18,6 +18,8 @@
  */
 package org.apache.metamodel.util;
 
+import java.util.function.Function;
+
 /**
  * Represents an abstract function, which is an executable piece of
  * functionality that has an input and an output. A {@link Func} has a return
@@ -27,8 +29,17 @@
  *            the input type
  * @param <O>
  *            the output type
+ * @deprecated use {@link Function} instead
  */
-public interface Func<I, O> {
+@Deprecated
+@FunctionalInterface
+public interface Func<I, O> extends Function<I, O> {
+    
+    @Override
+    default O apply(I t) {
+        // defer to the deprecated signature
+        return eval(t);
+    }
 
     /**
      * Evaluates an element and transforms it using this function.
diff --git a/core/src/main/java/org/apache/metamodel/util/HasNameMapper.java b/core/src/main/java/org/apache/metamodel/util/HasNameMapper.java
index 3b41102..e0d253b 100644
--- a/core/src/main/java/org/apache/metamodel/util/HasNameMapper.java
+++ b/core/src/main/java/org/apache/metamodel/util/HasNameMapper.java
@@ -19,18 +19,19 @@
 package org.apache.metamodel.util;
 
 import java.io.Serializable;
+import java.util.function.Function;
 
 /**
  * {@link Func} useful for mapping {@link HasName} instances to names, using
  * {@link CollectionUtils#map(Object[], Func)} and
  * {@link CollectionUtils#map(Iterable, Func)}.
  */
-public final class HasNameMapper implements Func<HasName, String>, Serializable {
+public final class HasNameMapper implements Function<HasName, String>, Serializable {
 
     private static final long serialVersionUID = 1L;
 
     @Override
-	public String eval(HasName arg) {
+	public String apply(HasName arg) {
 		return arg.getName();
 	}
 
diff --git a/core/src/main/java/org/apache/metamodel/util/ImmutableDate.java b/core/src/main/java/org/apache/metamodel/util/ImmutableDate.java
deleted file mode 100644
index b74c604..0000000
--- a/core/src/main/java/org/apache/metamodel/util/ImmutableDate.java
+++ /dev/null
@@ -1,61 +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.metamodel.util;
-
-import java.text.DateFormat;
-import java.util.Date;
-
-/**
- * A Date implementation that is immutable and has a predictable
- * (locale-indifferent) toString() method.
- * 
- * @deprecated MetaModel is not a Date API, use Joda time or live with
- *             java.util.Date.
- */
-@Deprecated
-public final class ImmutableDate extends Date {
-
-	private static final long serialVersionUID = 1L;
-
-	public ImmutableDate(long time) {
-		super(time);
-	}
-
-	public ImmutableDate(Date date) {
-		super(date.getTime());
-	}
-
-	/**
-	 * This mutator will throw an {@link UnsupportedOperationException}, since
-	 * the date is ummutable.
-	 * 
-	 * @param time
-	 *            new time to set
-	 */
-	@Override
-	public void setTime(long time) {
-		throw new UnsupportedOperationException("setTime(...) is not allowed");
-	}
-
-	@Override
-	public String toString() {
-		DateFormat format = DateUtils.createDateFormat();
-		return format.format(this);
-	}
-}
diff --git a/core/src/main/java/org/apache/metamodel/util/ImmutableRef.java b/core/src/main/java/org/apache/metamodel/util/ImmutableRef.java
index adfde04..beb0f76 100644
--- a/core/src/main/java/org/apache/metamodel/util/ImmutableRef.java
+++ b/core/src/main/java/org/apache/metamodel/util/ImmutableRef.java
@@ -18,26 +18,28 @@
  */
 package org.apache.metamodel.util;
 
+import java.util.function.Supplier;
+
 /**
  * Simple/hard implementation of the {@link Ref} interface.
  * 
  * @param <E>
  */
-public final class ImmutableRef<E> implements Ref<E> {
+public final class ImmutableRef<E> implements Supplier<E> {
 
-	private final E _object;
+    private final E _object;
 
-	public ImmutableRef(E object) {
-		_object = object;
-	}
+    public ImmutableRef(E object) {
+        _object = object;
+    }
 
-	@Override
-	public E get() {
-		return _object;
-	}
+    @Override
+    public E get() {
+        return _object;
+    }
 
-	public static <E> Ref<E> of(E object) {
-		return new ImmutableRef<E>(object);
-	}
+    public static <E> Supplier<E> of(E object) {
+        return new ImmutableRef<E>(object);
+    }
 
 }
diff --git a/core/src/main/java/org/apache/metamodel/util/InclusionPredicate.java b/core/src/main/java/org/apache/metamodel/util/InclusionPredicate.java
index d8aab91..4baa108 100644
--- a/core/src/main/java/org/apache/metamodel/util/InclusionPredicate.java
+++ b/core/src/main/java/org/apache/metamodel/util/InclusionPredicate.java
@@ -27,7 +27,7 @@
  * 
  * @param <E>
  */
-public class InclusionPredicate<E> implements Predicate<E> {
+public class InclusionPredicate<E> implements java.util.function.Predicate<E> {
 
     private final Collection<E> _inclusionList;
 
@@ -36,7 +36,7 @@
     }
 
     @Override
-    public Boolean eval(E arg) {
+    public boolean test(E arg) {
         if (_inclusionList.contains(arg)) {
             return true;
         }
diff --git a/core/src/main/java/org/apache/metamodel/util/LazyRef.java b/core/src/main/java/org/apache/metamodel/util/LazyRef.java
index 6db947d..24e3072 100644
--- a/core/src/main/java/org/apache/metamodel/util/LazyRef.java
+++ b/core/src/main/java/org/apache/metamodel/util/LazyRef.java
@@ -20,6 +20,7 @@
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -29,7 +30,7 @@
  * 
  * @param <E>
  */
-public abstract class LazyRef<E> implements Ref<E> {
+public abstract class LazyRef<E> implements Supplier<E> {
 
     private static final Logger logger = LoggerFactory.getLogger(LazyRef.class);
 
diff --git a/core/src/main/java/org/apache/metamodel/util/MutableRef.java b/core/src/main/java/org/apache/metamodel/util/MutableRef.java
index c5010a1..b6f2f88 100644
--- a/core/src/main/java/org/apache/metamodel/util/MutableRef.java
+++ b/core/src/main/java/org/apache/metamodel/util/MutableRef.java
@@ -18,12 +18,14 @@
  */
 package org.apache.metamodel.util;
 
+import java.util.function.Supplier;
+
 /**
  * Represents a mutable reference to any object
  * 
  * @param <E>
  */
-public final class MutableRef<E> implements Ref<E> {
+public final class MutableRef<E> implements Supplier<E> {
 
 	private E _object;
 
diff --git a/core/src/main/java/org/apache/metamodel/util/Predicate.java b/core/src/main/java/org/apache/metamodel/util/Predicate.java
index ef585e7..73e6a22 100644
--- a/core/src/main/java/org/apache/metamodel/util/Predicate.java
+++ b/core/src/main/java/org/apache/metamodel/util/Predicate.java
@@ -23,7 +23,16 @@
  * inclusion/exclusion criteria.
  * 
  * @param <E>
+ * 
+ * @deprecated use {@link java.util.function.Predicate} instead
  */
-public interface Predicate<E> extends Func<E, Boolean> {
+@Deprecated
+@FunctionalInterface
+public interface Predicate<E> extends Func<E, Boolean>, java.util.function.Predicate<E> {
 
+    @Override
+    default boolean test(E t) {
+        // delegate to the deprecated method signature
+        return eval(t);
+    }
 }
diff --git a/core/src/main/java/org/apache/metamodel/util/Ref.java b/core/src/main/java/org/apache/metamodel/util/Ref.java
index baa8e34..927c606 100644
--- a/core/src/main/java/org/apache/metamodel/util/Ref.java
+++ b/core/src/main/java/org/apache/metamodel/util/Ref.java
@@ -18,13 +18,20 @@
  */
 package org.apache.metamodel.util;
 
+import java.util.function.Supplier;
+
 /**
  * Represents an abstract reference. This interface enables use of both regular,
  * hard references, soft references and deferred/lazy references.
  * 
  * @param <E>
+ * 
+ * @deprecated use {@link Supplier} instead
  */
-public interface Ref<E> {
-
+@Deprecated
+@FunctionalInterface
+public interface Ref<E> extends Supplier<E> {
+    
+    @Override
 	public E get();
 }
diff --git a/core/src/main/java/org/apache/metamodel/util/Resource.java b/core/src/main/java/org/apache/metamodel/util/Resource.java
index becb79f..fe5386f 100644
--- a/core/src/main/java/org/apache/metamodel/util/Resource.java
+++ b/core/src/main/java/org/apache/metamodel/util/Resource.java
@@ -20,6 +20,7 @@
 
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.function.Function;
 
 /**
  * Represents a resource from which we can read and write bytes
@@ -159,5 +160,16 @@
      * @throws ResourceException
      *             if an error occurs while reading
      */
-    public <E> E read(Func<InputStream, E> readCallback) throws ResourceException;
+    public <E> E read(UncheckedFunc<InputStream, E> readCallback) throws ResourceException;
+
+    /**
+     * * Opens up an {@link InputStream} to read from the resource, and allows a
+     * callback function to perform writing actions on it and return the
+     * function's result.
+     * 
+     * @param readCallback
+     * @return
+     * @throws ResourceException
+     */
+    public <E> E read(Function<InputStream, E> readCallback) throws ResourceException;
 }
diff --git a/core/src/main/java/org/apache/metamodel/util/SerializableRef.java b/core/src/main/java/org/apache/metamodel/util/SerializableRef.java
index d3b56de..81a86f6 100644
--- a/core/src/main/java/org/apache/metamodel/util/SerializableRef.java
+++ b/core/src/main/java/org/apache/metamodel/util/SerializableRef.java
@@ -19,6 +19,7 @@
 package org.apache.metamodel.util;
 
 import java.io.Serializable;
+import java.util.function.Supplier;
 
 /**
  * A serializable reference to an object which may or may not be serializable.
@@ -27,7 +28,7 @@
  * 
  * @param <E>
  */
-public final class SerializableRef<E> implements Ref<E>, Serializable {
+public final class SerializableRef<E> implements Supplier<E>, Serializable {
 
     private static final long serialVersionUID = 1L;
 
diff --git a/core/src/main/java/org/apache/metamodel/util/TruePredicate.java b/core/src/main/java/org/apache/metamodel/util/TruePredicate.java
index f0d4745..e5acad4 100644
--- a/core/src/main/java/org/apache/metamodel/util/TruePredicate.java
+++ b/core/src/main/java/org/apache/metamodel/util/TruePredicate.java
@@ -25,12 +25,12 @@
  * 
  * @param <E>
  */
-public final class TruePredicate<E> implements Predicate<E>, Serializable {
+public final class TruePredicate<E> implements java.util.function.Predicate<E>, Serializable {
 
     private static final long serialVersionUID = 1L;
 
     @Override
-    public Boolean eval(E arg) {
+    public boolean test(E arg) {
         return true;
     }
     
diff --git a/core/src/main/java/org/apache/metamodel/util/UncheckedFunc.java b/core/src/main/java/org/apache/metamodel/util/UncheckedFunc.java
index ed5d89c..1e2b7dc 100644
--- a/core/src/main/java/org/apache/metamodel/util/UncheckedFunc.java
+++ b/core/src/main/java/org/apache/metamodel/util/UncheckedFunc.java
@@ -18,12 +18,22 @@
  */
 package org.apache.metamodel.util;
 
-public abstract class UncheckedFunc<I, O> implements Func<I, O> {
+import java.util.function.Function;
+
+/**
+ * Represents a {@link Function} that allows for throwing checked exceptions,
+ * making it more appropriate for encapsulating code blocks that may fail.
+ * 
+ * @param <I>
+ * @param <O>
+ */
+@FunctionalInterface
+public interface UncheckedFunc<I, O> extends Function<I, O> {
 
     @Override
-    public O eval(I arg) {
+    public default O apply(I arg) {
         try {
-            return evalUnchecked(arg);
+            return applyUnchecked(arg);
         } catch (Exception e) {
             if (e instanceof RuntimeException) {
                 throw (RuntimeException) e;
@@ -32,5 +42,5 @@
         }
     }
 
-    protected abstract O evalUnchecked(I arg) throws Exception;
+    public O applyUnchecked(I arg) throws Exception;
 }
diff --git a/core/src/test/java/org/apache/metamodel/MockUpdateableDataContext.java b/core/src/test/java/org/apache/metamodel/MockUpdateableDataContext.java
index b006a7c..8d6d48e 100644
--- a/core/src/test/java/org/apache/metamodel/MockUpdateableDataContext.java
+++ b/core/src/test/java/org/apache/metamodel/MockUpdateableDataContext.java
@@ -100,8 +100,8 @@
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
-        update.run(new AbstractUpdateCallback(this) {
+    public UpdateSummary executeUpdate(UpdateScript update) {
+        final AbstractUpdateCallback callback = new AbstractUpdateCallback(this) {
 
             @Override
             public boolean isDeleteSupported() {
@@ -153,7 +153,11 @@
                     IllegalStateException {
                 throw new UnsupportedOperationException();
             }
-        });
+        };
+        
+        update.run(callback);
+        
+        return callback.getUpdateSummary();
     }
 
     private void delete(List<FilterItem> whereItems) {
diff --git a/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java b/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java
index 6a8438a..d6955a9 100644
--- a/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java
+++ b/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java
@@ -494,8 +494,7 @@
         DataSet data = dc.executeQuery(q);
         assertEquals(1, data.getSelectItems().length);
 
-        @SuppressWarnings("deprecation")
-        TableModel tableModel = data.toTableModel();
+        TableModel tableModel = new DataSetTableModel(data);
 
         // should correspond to these lines:
 
@@ -537,8 +536,7 @@
         assertEquals(1, data.getSelectItems().length);
         assertEquals("SUM(r.project_id)", data.getSelectItems()[0].toString());
 
-        @SuppressWarnings("deprecation")
-        TableModel tableModel = data.toTableModel();
+        TableModel tableModel = new DataSetTableModel(data);
         assertEquals(3, tableModel.getRowCount());
         assertEquals(1, tableModel.getColumnCount());
         assertEquals(1.0, tableModel.getValueAt(0, 0));
diff --git a/core/src/test/java/org/apache/metamodel/data/DataSetTableModelTest.java b/core/src/test/java/org/apache/metamodel/data/DataSetTableModelTest.java
index 6ab60eb..b70bc8c 100644
--- a/core/src/test/java/org/apache/metamodel/data/DataSetTableModelTest.java
+++ b/core/src/test/java/org/apache/metamodel/data/DataSetTableModelTest.java
@@ -40,8 +40,7 @@
         rows.add(new DefaultRow(header, new Object[] { 2, "John", "Taylor" }));
         DataSet data = new InMemoryDataSet(header, rows);
 
-        @SuppressWarnings("deprecation")
-        TableModel tableModel = data.toTableModel();
+        TableModel tableModel = new DataSetTableModel(data);
         data.close();
 
         assertEquals(3, tableModel.getColumnCount());
diff --git a/core/src/test/java/org/apache/metamodel/data/UnionDataSetTest.java b/core/src/test/java/org/apache/metamodel/data/UnionDataSetTest.java
new file mode 100644
index 0000000..44178b2
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/data/UnionDataSetTest.java
@@ -0,0 +1,68 @@
+/**
+ * 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.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.apache.metamodel.schema.Column;
+import org.apache.metamodel.schema.MutableColumn;
+import org.junit.Test;
+
+public class UnionDataSetTest {
+
+    @Test
+    public void testVanillaUnion() {
+        // data set 1
+        final DataSetHeader header1 =
+                new SimpleDataSetHeader(new Column[] { new MutableColumn("foo1"), new MutableColumn("bar1") });
+        final Row row1 = new DefaultRow(header1, new Object[] { "1", "2" });
+        final Row row2 = new DefaultRow(header1, new Object[] { "3", "4" });
+        final DataSet ds1 = new InMemoryDataSet(header1, row1, row2);
+
+        // data set 2
+        final DataSetHeader header2 =
+                new SimpleDataSetHeader(new Column[] { new MutableColumn("foo2"), new MutableColumn("bar2") });
+        final Row row3 = new DefaultRow(header2, new Object[] { "5", "6" });
+        final DataSet ds2 = new InMemoryDataSet(header2, row3);
+
+        // data set 3
+        final DataSetHeader header3 =
+                new SimpleDataSetHeader(new Column[] { new MutableColumn("foo3"), new MutableColumn("bar3") });
+        final Row row4 = new DefaultRow(header2, new Object[] { "7", "8" });
+        final DataSet ds3 = new InMemoryDataSet(header3, row4);
+
+        final DataSetHeader unionHeader =
+                new SimpleDataSetHeader(new Column[] { new MutableColumn("fooUnion"), new MutableColumn("barUnion") });
+        final DataSet unionDataSet = UnionDataSet.ofDataSets(unionHeader, Arrays.asList(ds1, ds2, ds3));
+        assertTrue(unionDataSet.next());
+        assertEquals("Row[values=[1, 2]]", unionDataSet.getRow().toString());
+        assertTrue(unionDataSet.next());
+        assertEquals("Row[values=[3, 4]]", unionDataSet.getRow().toString());
+        assertTrue(unionDataSet.next());
+        assertEquals("Row[values=[5, 6]]", unionDataSet.getRow().toString());
+        assertTrue(unionDataSet.next());
+        assertEquals("Row[values=[7, 8]]", unionDataSet.getRow().toString());
+        assertFalse(unionDataSet.next());
+        unionDataSet.close();
+    }
+}
diff --git a/core/src/test/java/org/apache/metamodel/util/ClasspathResourceTest.java b/core/src/test/java/org/apache/metamodel/util/ClasspathResourceTest.java
index 72e49b8..885bf92 100644
--- a/core/src/test/java/org/apache/metamodel/util/ClasspathResourceTest.java
+++ b/core/src/test/java/org/apache/metamodel/util/ClasspathResourceTest.java
@@ -18,8 +18,6 @@
  */
 package org.apache.metamodel.util;
 
-import java.io.InputStream;
-
 import junit.framework.TestCase;
 
 public class ClasspathResourceTest extends TestCase {
@@ -29,17 +27,14 @@
         assertEquals("foo", resource.getName());
         assertTrue(resource.isExists());
         assertTrue(resource.isReadOnly());
-        
+
         resource = new ClasspathResource("/folder/foo");
         assertEquals("foo", resource.getName());
         assertTrue(resource.isExists());
         assertTrue(resource.isReadOnly());
-        
-        String result = resource.read(new Func<InputStream, String>() {
-            @Override
-            public String eval(InputStream inputStream) {
-                return FileHelper.readInputStreamAsString(inputStream, "UTF8");
-            }
+
+        String result = resource.read(inputStream -> {
+            return FileHelper.readInputStreamAsString(inputStream, "UTF8");
         });
         assertEquals("bar-baz", result);
     }
diff --git a/core/src/test/java/org/apache/metamodel/util/CollectionUtilsTest.java b/core/src/test/java/org/apache/metamodel/util/CollectionUtilsTest.java
index 5b1f013..c5a5a6f 100644
--- a/core/src/test/java/org/apache/metamodel/util/CollectionUtilsTest.java
+++ b/core/src/test/java/org/apache/metamodel/util/CollectionUtilsTest.java
@@ -73,7 +73,7 @@
         assertEquals("Stockholm", CollectionUtils.find(map, "Person.Addresses[0].city").toString());
         assertEquals("{city=Copenhagen, country=Denmark}", CollectionUtils.find(map, "Person.Addresses[1]").toString());
         assertEquals(null, CollectionUtils.find(map, "Person.Addresses[4].country"));
-        
+
         assertEquals(null, CollectionUtils.find(map, "Foo.bar"));
         assertEquals(null, CollectionUtils.find(map, "Person.Addresses.Foo"));
     }
@@ -111,12 +111,7 @@
         strings.add("hi");
         strings.add("world");
 
-        List<Integer> ints = CollectionUtils.map(strings, new Func<String, Integer>() {
-            @Override
-            public Integer eval(String arg) {
-                return arg.length();
-            }
-        });
+        List<Integer> ints = CollectionUtils.map(strings, String::length);
         assertEquals("[2, 5]", ints.toString());
     }
 
@@ -127,12 +122,7 @@
         list.add("3");
         list.add("2");
 
-        list = CollectionUtils.filter(list, new Predicate<String>() {
-            @Override
-            public Boolean eval(String arg) {
-                return arg.length() > 1;
-            }
-        });
+        list = CollectionUtils.filter(list, arg -> arg.length() > 1);
 
         assertEquals(2, list.size());
         assertEquals("[foo, bar]", list.toString());
diff --git a/core/src/test/java/org/apache/metamodel/util/ExclusionPredicateTest.java b/core/src/test/java/org/apache/metamodel/util/ExclusionPredicateTest.java
index 405f9b3..ed11cc8 100644
--- a/core/src/test/java/org/apache/metamodel/util/ExclusionPredicateTest.java
+++ b/core/src/test/java/org/apache/metamodel/util/ExclusionPredicateTest.java
@@ -27,10 +27,10 @@
     public void testEval() throws Exception {
         ExclusionPredicate<String> predicate = new ExclusionPredicate<String>(Arrays.asList("foo","bar","baz"));
         
-        assertFalse(predicate.eval("foo"));
-        assertFalse(predicate.eval("bar"));
-        assertFalse(predicate.eval("baz"));
+        assertFalse(predicate.test("foo"));
+        assertFalse(predicate.test("bar"));
+        assertFalse(predicate.test("baz"));
         
-        assertTrue(predicate.eval("hello world"));
+        assertTrue(predicate.test("hello world"));
     }
 }
diff --git a/core/src/test/java/org/apache/metamodel/util/FileResourceTest.java b/core/src/test/java/org/apache/metamodel/util/FileResourceTest.java
index d0b8405..e305a6c 100644
--- a/core/src/test/java/org/apache/metamodel/util/FileResourceTest.java
+++ b/core/src/test/java/org/apache/metamodel/util/FileResourceTest.java
@@ -18,9 +18,10 @@
  */
 package org.apache.metamodel.util;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Arrays;
 import java.util.Collections;
@@ -38,7 +39,7 @@
     public void testCannotWriteToDirectory() throws Exception {
         FileResource dir = new FileResource(".");
         assertTrue(dir.isReadOnly());
-        
+
         try {
             dir.write();
             fail("Exception expected");
@@ -76,20 +77,14 @@
 
         final FileResource res1 = new FileResource(folder.getRoot());
 
-        final String str1 = res1.read(new Func<InputStream, String>() {
-            @Override
-            public String eval(InputStream in) {
-                return FileHelper.readInputStreamAsString(in, "UTF8");
-            }
+        final String str1 = res1.read(in -> {
+            return FileHelper.readInputStreamAsString(in, "UTF8");
         });
 
         Assert.assertEquals(contentString, str1);
 
-        final String str2 = res1.read(new Func<InputStream, String>() {
-            @Override
-            public String eval(InputStream in) {
+        final String str2 = res1.read(in -> {
                 return FileHelper.readInputStreamAsString(in, "UTF8");
-            }
         });
         Assert.assertEquals(str1, str2);
     }
diff --git a/core/src/test/java/org/apache/metamodel/util/InclusionPredicateTest.java b/core/src/test/java/org/apache/metamodel/util/InclusionPredicateTest.java
index c3866e3..a3b4857 100644
--- a/core/src/test/java/org/apache/metamodel/util/InclusionPredicateTest.java
+++ b/core/src/test/java/org/apache/metamodel/util/InclusionPredicateTest.java
@@ -27,10 +27,10 @@
     public void testEval() throws Exception {
         InclusionPredicate<String> predicate = new InclusionPredicate<String>(Arrays.asList("foo","bar","baz"));
         
-        assertTrue(predicate.eval("foo"));
-        assertTrue(predicate.eval("bar"));
-        assertTrue(predicate.eval("baz"));
+        assertTrue(predicate.test("foo"));
+        assertTrue(predicate.test("bar"));
+        assertTrue(predicate.test("baz"));
         
-        assertFalse(predicate.eval("hello world"));
+        assertFalse(predicate.test("hello world"));
     }
 }
diff --git a/core/src/test/java/org/apache/metamodel/util/SimpleRefTest.java b/core/src/test/java/org/apache/metamodel/util/SimpleRefTest.java
index 8b4ec47..d128d63 100644
--- a/core/src/test/java/org/apache/metamodel/util/SimpleRefTest.java
+++ b/core/src/test/java/org/apache/metamodel/util/SimpleRefTest.java
@@ -18,12 +18,14 @@
  */
 package org.apache.metamodel.util;
 
+import java.util.function.Supplier;
+
 import junit.framework.TestCase;
 
 public class SimpleRefTest extends TestCase {
 
 	public void testGet() throws Exception {
-		Ref<String> lazyRef = new ImmutableRef<String>("foo");
+		Supplier<String> lazyRef = new ImmutableRef<String>("foo");
 
 		assertEquals("foo", lazyRef.get());
 
diff --git a/couchdb/pom.xml b/couchdb/pom.xml
index e9569a8..402762d 100644
--- a/couchdb/pom.xml
+++ b/couchdb/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-couchdb</artifactId>
diff --git a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbDataContext.java b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbDataContext.java
index 33cab20..f98fa81 100644
--- a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbDataContext.java
+++ b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbDataContext.java
@@ -24,6 +24,7 @@
 import org.apache.metamodel.MetaModelHelper;
 import org.apache.metamodel.QueryPostprocessDataContext;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.DocumentSource;
@@ -167,13 +168,14 @@
     }
 
     @Override
-    public void executeUpdate(UpdateScript script) {
-        CouchDbUpdateCallback callback = new CouchDbUpdateCallback(this);
+    public UpdateSummary executeUpdate(UpdateScript script) {
+        final CouchDbUpdateCallback callback = new CouchDbUpdateCallback(this);
         try {
             script.run(callback);
         } finally {
             callback.close();
         }
+        return callback.getUpdateSummary();
     }
 
     @Override
diff --git a/csv/pom.xml b/csv/pom.xml
index 31493a0..1b7c8b9 100644
--- a/csv/pom.xml
+++ b/csv/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-csv</artifactId>
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvDataContext.java b/csv/src/main/java/org/apache/metamodel/csv/CsvDataContext.java
index c8df5a7..2e66ebe 100644
--- a/csv/src/main/java/org/apache/metamodel/csv/CsvDataContext.java
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvDataContext.java
@@ -33,6 +33,7 @@
 import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.QueryPostprocessDataContext;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.EmptyDataSet;
@@ -41,7 +42,6 @@
 import org.apache.metamodel.schema.Table;
 import org.apache.metamodel.util.FileHelper;
 import org.apache.metamodel.util.FileResource;
-import org.apache.metamodel.util.Func;
 import org.apache.metamodel.util.Resource;
 import org.apache.metamodel.util.ResourceUtils;
 import org.apache.metamodel.util.UrlResource;
@@ -69,9 +69,9 @@
     /**
      * Constructs a CSV DataContext based on a file
      *
-     * The file provided can be either existing or non-existing. In the
-     * case of non-existing files, a file will be automatically created
-     * when a CREATE TABLE update is executed on the DataContext.
+     * The file provided can be either existing or non-existing. In the case of
+     * non-existing files, a file will be automatically created when a CREATE
+     * TABLE update is executed on the DataContext.
      * 
      * @param file
      * @param configuration
@@ -135,69 +135,6 @@
     }
 
     /**
-     * @deprecated use {@link #CsvDataContext(File, CsvConfiguration)} instead.
-     */
-    @Deprecated
-    public CsvDataContext(File file, char separatorChar) {
-        this(file, separatorChar, CsvConfiguration.DEFAULT_QUOTE_CHAR);
-    }
-
-    /**
-     * @deprecated use {@link #CsvDataContext(File, CsvConfiguration)} instead.
-     */
-    @Deprecated
-    public CsvDataContext(File file, char separatorChar, char quoteChar) {
-        this(file, new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, FileHelper.DEFAULT_ENCODING,
-                separatorChar, quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR));
-    }
-
-    /**
-     * @deprecated use {@link #CsvDataContext(File, CsvConfiguration)} instead.
-     */
-    @Deprecated
-    public CsvDataContext(File file, char separatorChar, char quoteChar, String encoding) {
-        this(file, new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar, quoteChar,
-                CsvConfiguration.DEFAULT_ESCAPE_CHAR));
-    }
-
-    /**
-     * @deprecated use {@link #CsvDataContext(URL, CsvConfiguration)} instead.
-     */
-    @Deprecated
-    public CsvDataContext(URL url, char separatorChar, char quoteChar) {
-        this(url, separatorChar, quoteChar, FileHelper.DEFAULT_ENCODING);
-    }
-
-    /**
-     * @deprecated use {@link #CsvDataContext(URL, CsvConfiguration)} instead.
-     */
-    @Deprecated
-    public CsvDataContext(URL url, char separatorChar, char quoteChar, String encoding) {
-        this(url, new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar, quoteChar,
-                CsvConfiguration.DEFAULT_ESCAPE_CHAR));
-    }
-
-    /**
-     * @deprecated use {@link #CsvDataContext(InputStream, CsvConfiguration)}
-     *             instead.
-     */
-    @Deprecated
-    public CsvDataContext(InputStream inputStream, char separatorChar, char quoteChar) {
-        this(inputStream, new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, FileHelper.DEFAULT_ENCODING,
-                separatorChar, quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR));
-    }
-
-    /**
-     * @deprecated use {@link #CsvDataContext(InputStream, CsvConfiguration)}
-     *             instead.
-     */
-    @Deprecated
-    public CsvDataContext(InputStream inputStream, char separatorChar, char quoteChar, String encoding) {
-        this(inputStream, new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar,
-                quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR));
-    }
-
-    /**
      * Gets the CSV configuration used
      * 
      * @return a CSV configuration
@@ -207,21 +144,6 @@
     }
 
     /**
-     * Gets the CSV file being read
-     * 
-     * @return a file
-     * 
-     * @deprecated use {@link #getResource()} instead.
-     */
-    @Deprecated
-    public File getFile() {
-        if (_resource instanceof FileResource) {
-            return ((FileResource) _resource).getFile();
-        }
-        return null;
-    }
-
-    /**
      * Gets the resource that is being read from.
      * 
      * @return
@@ -276,62 +198,59 @@
         if (!functionApproximationAllowed) {
             return null;
         }
-        
+
         if (whereItems != null && !whereItems.isEmpty()) {
             return null;
         }
-        
+
         final long length = _resource.getSize();
         if (length < 0) {
             // METAMODEL-30: Sometimes the size of the resource is not known
             return null;
         }
 
-        return _resource.read(new Func<InputStream, Number>() {
-            @Override
-            public Number eval(InputStream inputStream) {
-                try {
-                    // read up to 5 megs of the file and approximate number of
-                    // lines based on that.
+        return _resource.read(inputStream -> {
+            try {
+                // read up to 5 megs of the file and approximate number of
+                // lines based on that.
 
-                    final int sampleSize = (int) Math.min(length, 1024 * 1024 * 5);
-                    final int chunkSize = Math.min(sampleSize, 1024 * 1024);
+                final int sampleSize = (int) Math.min(length, 1024 * 1024 * 5);
+                final int chunkSize = Math.min(sampleSize, 1024 * 1024);
 
-                    int readSize = 0;
-                    int newlines = 0;
-                    int carriageReturns = 0;
-                    byte[] byteBuffer = new byte[chunkSize];
-                    char[] charBuffer = new char[chunkSize];
+                int readSize = 0;
+                int newlines = 0;
+                int carriageReturns = 0;
+                byte[] byteBuffer = new byte[chunkSize];
+                char[] charBuffer = new char[chunkSize];
 
-                    while (readSize < sampleSize) {
-                        final int read = inputStream.read(byteBuffer);
-                        if (read == -1) {
-                            break;
-                        } else {
-                            readSize += read;
-                        }
-
-                        Reader reader = getReader(byteBuffer, _configuration.getEncoding());
-                        reader.read(charBuffer);
-                        for (char c : charBuffer) {
-                            if ('\n' == c) {
-                                newlines++;
-                            } else if ('\r' == c) {
-                                carriageReturns++;
-                            }
-                        }
+                while (readSize < sampleSize) {
+                    final int read = inputStream.read(byteBuffer);
+                    if (read == -1) {
+                        break;
+                    } else {
+                        readSize += read;
                     }
 
-                    int lines = Math.max(newlines, carriageReturns);
-
-                    logger.info("Found {} lines breaks in {} bytes", lines, sampleSize);
-
-                    long approxCount = (long) (lines * length / sampleSize);
-                    return approxCount;
-                } catch (IOException e) {
-                    logger.error("Unexpected error during COUNT(*) approximation", e);
-                    throw new IllegalStateException(e);
+                    Reader reader = getReader(byteBuffer, _configuration.getEncoding());
+                    reader.read(charBuffer);
+                    for (char c : charBuffer) {
+                        if ('\n' == c) {
+                            newlines++;
+                        } else if ('\r' == c) {
+                            carriageReturns++;
+                        }
+                    }
                 }
+
+                int lines = Math.max(newlines, carriageReturns);
+
+                logger.info("Found {} lines breaks in {} bytes", lines, sampleSize);
+
+                long approxCount = (long) (lines * length / sampleSize);
+                return approxCount;
+            } catch (IOException e) {
+                logger.error("Unexpected error during COUNT(*) approximation", e);
+                throw new IllegalStateException(e);
             }
         });
     }
@@ -432,9 +351,10 @@
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
+    public UpdateSummary executeUpdate(UpdateScript update) {
         checkWritable();
-        CsvUpdateCallback callback = new CsvUpdateCallback(this);
+        
+        final CsvUpdateCallback callback = new CsvUpdateCallback(this);
         synchronized (WRITE_LOCK) {
             try {
                 update.run(callback);
@@ -442,5 +362,6 @@
                 callback.close();
             }
         }
+        return callback.getUpdateSummary();
     }
 }
\ No newline at end of file
diff --git a/dynamodb/pom.xml b/dynamodb/pom.xml
index ec95902..1de0cb3 100644
--- a/dynamodb/pom.xml
+++ b/dynamodb/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-dynamodb</artifactId>
diff --git a/dynamodb/src/main/java/org/apache/metamodel/dynamodb/DynamoDbDataContext.java b/dynamodb/src/main/java/org/apache/metamodel/dynamodb/DynamoDbDataContext.java
index 5f95219..255120c 100644
--- a/dynamodb/src/main/java/org/apache/metamodel/dynamodb/DynamoDbDataContext.java
+++ b/dynamodb/src/main/java/org/apache/metamodel/dynamodb/DynamoDbDataContext.java
@@ -28,6 +28,7 @@
 import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.QueryPostprocessDataContext;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.DefaultRow;
@@ -293,7 +294,7 @@
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
+    public UpdateSummary executeUpdate(UpdateScript update) {
         final DynamoDbUpdateCallback callback = new DynamoDbUpdateCallback(this);
         try {
             update.run(callback);
@@ -302,5 +303,6 @@
                 Thread.currentThread().interrupt();
             }
         }
+        return callback.getUpdateSummary();
     }
 }
diff --git a/elasticsearch/common/pom.xml b/elasticsearch/common/pom.xml
index 70625ec..90ba8d0 100644
--- a/elasticsearch/common/pom.xml
+++ b/elasticsearch/common/pom.xml
@@ -13,7 +13,7 @@
 	<parent>
 		<artifactId>MetaModel-elasticsearch</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 
diff --git a/elasticsearch/native/pom.xml b/elasticsearch/native/pom.xml
index dfae6ed..36f5ed6 100644
--- a/elasticsearch/native/pom.xml
+++ b/elasticsearch/native/pom.xml
@@ -13,7 +13,7 @@
 	<parent>
 		<artifactId>MetaModel-elasticsearch</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 
diff --git a/elasticsearch/native/src/main/java/org/apache/metamodel/elasticsearch/nativeclient/ElasticSearchDataContext.java b/elasticsearch/native/src/main/java/org/apache/metamodel/elasticsearch/nativeclient/ElasticSearchDataContext.java
index acd0c36..7353cbd 100644
--- a/elasticsearch/native/src/main/java/org/apache/metamodel/elasticsearch/nativeclient/ElasticSearchDataContext.java
+++ b/elasticsearch/native/src/main/java/org/apache/metamodel/elasticsearch/nativeclient/ElasticSearchDataContext.java
@@ -29,6 +29,7 @@
 import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.QueryPostprocessDataContext;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.DataSetHeader;
@@ -90,7 +91,8 @@
 
     private final Client elasticSearchClient;
     private final String indexName;
-    // Table definitions that are set from the beginning, not supposed to be changed.
+    // Table definitions that are set from the beginning, not supposed to be
+    // changed.
     private final List<SimpleTableDef> staticTableDefinitions;
 
     // Table definitions that are discovered, these can change
@@ -149,8 +151,8 @@
         logger.info("Detecting schema for index '{}'", indexName);
 
         final ClusterState cs;
-        final ClusterStateRequestBuilder clusterStateRequestBuilder =
-                getElasticSearchClient().admin().cluster().prepareState();
+        final ClusterStateRequestBuilder clusterStateRequestBuilder = getElasticSearchClient().admin().cluster()
+                .prepareState();
 
         // different methods here to set the index name, so we have to use
         // reflection :-/
@@ -280,7 +282,8 @@
     @Override
     protected DataSet materializeMainSchemaTable(Table table, List<SelectItem> selectItems,
             List<FilterItem> whereItems, int firstRow, int maxRows) {
-        final QueryBuilder queryBuilder = ElasticSearchUtils.createQueryBuilderForSimpleWhere(whereItems, LogicalOperator.AND);
+        final QueryBuilder queryBuilder = ElasticSearchUtils.createQueryBuilderForSimpleWhere(whereItems,
+                LogicalOperator.AND);
         if (queryBuilder != null) {
             // where clause can be pushed down to an ElasticSearch query
             final SearchRequestBuilder searchRequest = createSearchRequest(table, firstRow, maxRows, queryBuilder);
@@ -358,10 +361,11 @@
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
+    public UpdateSummary executeUpdate(UpdateScript update) {
         final ElasticSearchUpdateCallback callback = new ElasticSearchUpdateCallback(this);
         update.run(callback);
         callback.onExecuteUpdateFinished();
+        return callback.getUpdateSummary();
     }
 
     /**
diff --git a/elasticsearch/pom.xml b/elasticsearch/pom.xml
index e5ee1d8..77223fa 100644
--- a/elasticsearch/pom.xml
+++ b/elasticsearch/pom.xml
@@ -13,7 +13,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-elasticsearch</artifactId>
diff --git a/elasticsearch/rest/pom.xml b/elasticsearch/rest/pom.xml
index c0f802a..45c889d 100644
--- a/elasticsearch/rest/pom.xml
+++ b/elasticsearch/rest/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel-elasticsearch</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 
 	<modelVersion>4.0.0</modelVersion>
diff --git a/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContext.java b/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContext.java
index 920217f..57ad267 100644
--- a/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContext.java
+++ b/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContext.java
@@ -31,6 +31,7 @@
 import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.QueryPostprocessDataContext;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.DataSetHeader;
@@ -84,8 +85,7 @@
  * This implementation supports either automatic discovery of a schema or manual
  * specification of a schema, through the {@link SimpleTableDef} class.
  */
-public class ElasticSearchRestDataContext extends QueryPostprocessDataContext implements
-        DataContext,
+public class ElasticSearchRestDataContext extends QueryPostprocessDataContext implements DataContext,
         UpdateableDataContext {
 
     private static final Logger logger = LoggerFactory.getLogger(ElasticSearchRestDataContext.class);
@@ -261,8 +261,8 @@
     }
 
     @Override
-    protected DataSet materializeMainSchemaTable(Table table, List<SelectItem> selectItems, List<FilterItem> whereItems,
-            int firstRow, int maxRows) {
+    protected DataSet materializeMainSchemaTable(Table table, List<SelectItem> selectItems,
+            List<FilterItem> whereItems, int firstRow, int maxRows) {
         final QueryBuilder queryBuilder = ElasticSearchUtils.createQueryBuilderForSimpleWhere(whereItems,
                 LogicalOperator.AND);
         if (queryBuilder != null) {
@@ -371,11 +371,12 @@
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
+    public UpdateSummary executeUpdate(UpdateScript update) {
         final boolean isBatch = update instanceof BatchUpdateScript;
         final JestElasticSearchUpdateCallback callback = new JestElasticSearchUpdateCallback(this, isBatch);
         update.run(callback);
         callback.onExecuteUpdateFinished();
+        return callback.getUpdateSummary();
     }
 
     /**
diff --git a/excel/pom.xml b/excel/pom.xml
index 83746ce..fd39674 100644
--- a/excel/pom.xml
+++ b/excel/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-excel</artifactId>
diff --git a/excel/src/main/java/org/apache/metamodel/excel/ExcelDataContext.java b/excel/src/main/java/org/apache/metamodel/excel/ExcelDataContext.java
index 0ce1c64..9ef931b 100644
--- a/excel/src/main/java/org/apache/metamodel/excel/ExcelDataContext.java
+++ b/excel/src/main/java/org/apache/metamodel/excel/ExcelDataContext.java
@@ -26,6 +26,7 @@
 import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.QueryPostprocessDataContext;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.schema.Column;
@@ -113,20 +114,6 @@
     }
 
     /**
-     * Gets the Excel file being read.
-     * 
-     * @return a file.
-     * @deprecated
-     */
-    @Deprecated
-    public File getFile() {
-        if (_resource instanceof FileResource) {
-            return ((FileResource) _resource).getFile();
-        }
-        return null;
-    }
-
-    /**
      * Gets the Excel resource being read
      * 
      * @return
@@ -225,8 +212,8 @@
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
-        ExcelUpdateCallback updateCallback = new ExcelUpdateCallback(this);
+    public UpdateSummary executeUpdate(UpdateScript update) {
+        final ExcelUpdateCallback updateCallback = new ExcelUpdateCallback(this);
         synchronized (WRITE_LOCK) {
             try {
                 update.run(updateCallback);
@@ -234,5 +221,6 @@
                 updateCallback.close();
             }
         }
+        return updateCallback.getUpdateSummary();
     }
 }
\ No newline at end of file
diff --git a/excel/src/test/java/org/apache/metamodel/excel/ExcelDataContextTest.java b/excel/src/test/java/org/apache/metamodel/excel/ExcelDataContextTest.java
index f8406c3..ecd6691 100644
--- a/excel/src/test/java/org/apache/metamodel/excel/ExcelDataContextTest.java
+++ b/excel/src/test/java/org/apache/metamodel/excel/ExcelDataContextTest.java
@@ -22,8 +22,6 @@
 import java.util.Arrays;
 import java.util.List;
 
-import junit.framework.TestCase;
-
 import org.apache.metamodel.DataContext;
 import org.apache.metamodel.MetaModelHelper;
 import org.apache.metamodel.UpdateCallback;
@@ -39,8 +37,11 @@
 import org.apache.metamodel.schema.naming.CustomColumnNamingStrategy;
 import org.apache.metamodel.util.DateUtils;
 import org.apache.metamodel.util.FileHelper;
+import org.apache.metamodel.util.FileResource;
 import org.apache.metamodel.util.Month;
 
+import junit.framework.TestCase;
+
 public class ExcelDataContextTest extends TestCase {
 
     /**
@@ -74,7 +75,6 @@
         }
     }
 
-    @SuppressWarnings("deprecation")
     public void testEmptyFile() throws Exception {
         File file = copyOf("src/test/resources/empty_file.xls");
         ExcelDataContext dc = new ExcelDataContext(file);
@@ -86,7 +86,7 @@
         assertEquals("sheet", table.getName());
         assertEquals(0, table.getColumnCount());
 
-        assertSame(file, dc.getFile());
+        assertSame(file, ((FileResource) dc.getResource()).getFile());
     }
 
     public void testEmptyFileNoHeaderLine() throws Exception {
diff --git a/fixedwidth/pom.xml b/fixedwidth/pom.xml
index 4cf4760..5a79a09 100644
--- a/fixedwidth/pom.xml
+++ b/fixedwidth/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-fixedwidth</artifactId>
diff --git a/fixedwidth/src/main/java/org/apache/metamodel/fixedwidth/FixedWidthColumnSpec.java b/fixedwidth/src/main/java/org/apache/metamodel/fixedwidth/FixedWidthColumnSpec.java
index 5f53ff5..f9d62df 100644
--- a/fixedwidth/src/main/java/org/apache/metamodel/fixedwidth/FixedWidthColumnSpec.java
+++ b/fixedwidth/src/main/java/org/apache/metamodel/fixedwidth/FixedWidthColumnSpec.java
@@ -24,7 +24,7 @@
  * Represents the specification of a single column for a
  * {@link FixedWidthDataContext}.
  */
-final class FixedWidthColumnSpec implements HasName {
+public final class FixedWidthColumnSpec implements HasName {
 
     private final String name;
     private final int width;
diff --git a/fixedwidth/src/main/java/org/apache/metamodel/fixedwidth/FixedWidthDataContext.java b/fixedwidth/src/main/java/org/apache/metamodel/fixedwidth/FixedWidthDataContext.java
index 027cdab..952c4b5 100644
--- a/fixedwidth/src/main/java/org/apache/metamodel/fixedwidth/FixedWidthDataContext.java
+++ b/fixedwidth/src/main/java/org/apache/metamodel/fixedwidth/FixedWidthDataContext.java
@@ -49,26 +49,6 @@
     private final Resource _resource;
     private final FixedWidthConfiguration _configuration;
 
-    /**
-     * @deprecated use
-     *             {@link #FixedWidthDataContext(File, FixedWidthConfiguration)}
-     *             instead
-     */
-    @Deprecated
-    public FixedWidthDataContext(String filename, String fileEncoding, int fixedValueWidth) {
-        this(new FileResource(filename), new FixedWidthConfiguration(fixedValueWidth));
-    }
-
-    /**
-     * @deprecated use
-     *             {@link #FixedWidthDataContext(File, FixedWidthConfiguration)}
-     *             instead
-     */
-    @Deprecated
-    public FixedWidthDataContext(File file, String fileEncoding, int fixedValueWidth, int headerLineNumber) {
-        this(file, new FixedWidthConfiguration(headerLineNumber, fileEncoding, fixedValueWidth));
-    }
-
     public FixedWidthDataContext(File file, FixedWidthConfiguration configuration) {
         _resource = new FileResource(file);
         _configuration = configuration;
@@ -89,21 +69,6 @@
     }
 
     /**
-     * Gets the file being read.
-     * 
-     * @return a file
-     * 
-     * @deprecated use {@link #getResource()} instead.
-     */
-    @Deprecated
-    public File getFile() {
-        if (_resource instanceof FileResource) {
-            return ((FileResource) _resource).getFile();
-        }
-        return null;
-    }
-
-    /**
      * Gets the resource being read
      * 
      * @return a {@link Resource} object
diff --git a/full/pom.xml b/full/pom.xml
index 14fbc92..16cc2b4 100644
--- a/full/pom.xml
+++ b/full/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-full</artifactId>
diff --git a/full/src/main/java/org/apache/metamodel/DataContextFactory.java b/full/src/main/java/org/apache/metamodel/DataContextFactory.java
index af12604..427101e 100644
--- a/full/src/main/java/org/apache/metamodel/DataContextFactory.java
+++ b/full/src/main/java/org/apache/metamodel/DataContextFactory.java
@@ -558,6 +558,7 @@
      *            should be autodetected.
      * @return a DataContext object that matches the request
      */
+    @SuppressWarnings("resource")
     public static UpdateableDataContext createMongoDbDataContext(String hostname, Integer port, String databaseName,
             String username, char[] password, SimpleTableDef[] tableDefs) {
         try {
diff --git a/hadoop/pom.xml b/hadoop/pom.xml
index badc52e..0636bba 100644
--- a/hadoop/pom.xml
+++ b/hadoop/pom.xml
@@ -13,7 +13,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-hadoop</artifactId>
diff --git a/hadoop/src/test/java/org/apache/metamodel/util/HdfsResourceIntegrationTest.java b/hadoop/src/test/java/org/apache/metamodel/util/HdfsResourceIntegrationTest.java
index e6119b8..ca2aa2f 100644
--- a/hadoop/src/test/java/org/apache/metamodel/util/HdfsResourceIntegrationTest.java
+++ b/hadoop/src/test/java/org/apache/metamodel/util/HdfsResourceIntegrationTest.java
@@ -98,8 +98,8 @@
         int i = contents.length;
         Collections.reverse(Arrays.asList(contents));
         for (final String contentPart : contents) {
-            final HdfsResource partResource = new HdfsResource(_hostname, _port,
-                    _filePath + "/part-" + String.format("%02d", i--));
+            final HdfsResource partResource = new HdfsResource(_hostname, _port, _filePath + "/part-" + String.format(
+                    "%02d", i--));
             partResource.write(new Action<OutputStream>() {
                 @Override
                 public void run(OutputStream out) throws Exception {
@@ -113,21 +113,15 @@
         try {
             logger.info(stopwatch.elapsed(TimeUnit.MILLISECONDS) + " - start");
 
-            final String str1 = res1.read(new Func<InputStream, String>() {
-                @Override
-                public String eval(InputStream in) {
-                    return FileHelper.readInputStreamAsString(in, "UTF8");
-                }
+            final String str1 = res1.read(in -> {
+                return FileHelper.readInputStreamAsString(in, "UTF8");
             });
 
             Assert.assertEquals(contentString, str1);
             logger.info(stopwatch.elapsed(TimeUnit.MILLISECONDS) + " - read1");
 
-            final String str2 = res1.read(new Func<InputStream, String>() {
-                @Override
-                public String eval(InputStream in) {
-                    return FileHelper.readInputStreamAsString(in, "UTF8");
-                }
+            final String str2 = res1.read(in -> {
+                return FileHelper.readInputStreamAsString(in, "UTF8");
             });
             Assert.assertEquals(str1, str2);
             logger.info(stopwatch.elapsed(TimeUnit.MILLISECONDS) + " - read2");
@@ -173,20 +167,14 @@
 
         Assert.assertTrue(res1.isExists());
 
-        final String str1 = res1.read(new Func<InputStream, String>() {
-            @Override
-            public String eval(InputStream in) {
-                return FileHelper.readInputStreamAsString(in, "UTF8");
-            }
+        final String str1 = res1.read(in -> {
+            return FileHelper.readInputStreamAsString(in, "UTF8");
         });
         Assert.assertEquals(contentString, str1);
         logger.info(stopwatch.elapsed(TimeUnit.MILLISECONDS) + " - read1");
 
-        final String str2 = res1.read(new Func<InputStream, String>() {
-            @Override
-            public String eval(InputStream in) {
-                return FileHelper.readInputStreamAsString(in, "UTF8");
-            }
+        final String str2 = res1.read(in -> {
+            return FileHelper.readInputStreamAsString(in, "UTF8");
         });
         Assert.assertEquals(str1, str2);
         logger.info(stopwatch.elapsed(TimeUnit.MILLISECONDS) + " - read2");
@@ -243,7 +231,7 @@
 
                     }
                 });
-                
+
                 thread.setUncaughtExceptionHandler(exceptionHandler);
                 thread.start();
                 threads[i] = thread;
@@ -252,12 +240,12 @@
             for (int i = 0; i < threads.length; i++) {
                 threads[i].join();
             }
-            
+
             Throwable error = throwableRef.get();
             if (error != null) {
                 throw error;
             }
-            
+
         } finally {
             if (resourceToRead != null) {
                 final FileSystem fileSystem = resourceToRead.getHadoopFileSystem();
diff --git a/hbase/pom.xml b/hbase/pom.xml
index 963e0b4..9f7857d 100644
--- a/hbase/pom.xml
+++ b/hbase/pom.xml
@@ -13,7 +13,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-hbase</artifactId>
diff --git a/jdbc/pom.xml b/jdbc/pom.xml
index e5f8deb..91aefc5 100644
--- a/jdbc/pom.xml
+++ b/jdbc/pom.xml
@@ -13,7 +13,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-jdbc</artifactId>
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcBatchUpdateCallback.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcBatchUpdateCallback.java
index 100c5d0..52478fc 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcBatchUpdateCallback.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcBatchUpdateCallback.java
@@ -68,7 +68,13 @@
     }
 
     @Override
-    protected void executePreparedStatement(PreparedStatement st) throws SQLException {
+    protected int executePreparedStatement(PreparedStatement st) throws SQLException {
         st.addBatch();
+        return -1;
+    }
+    
+    @Override
+    protected boolean isGeneratedKeysCollectionEnabled() {
+        return false;
     }
 }
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 ef0b549..5a9b784 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java
@@ -39,6 +39,7 @@
 import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.MetaModelHelper;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.EmptyDataSet;
@@ -343,6 +344,7 @@
         return dataSet;
     }
 
+    @SuppressWarnings("resource")
     private DataSet execute(Connection connection, Query query, Statement statement, JdbcCompiledQuery compiledQuery,
             JdbcCompiledQueryLease lease, Object[] values) throws SQLException, MetaModelException {
         Integer maxRows = query.getMaxRows();
@@ -841,7 +843,7 @@
     }
 
     @Override
-    public void executeUpdate(final UpdateScript update) {
+    public UpdateSummary executeUpdate(final UpdateScript update) {
         final JdbcUpdateCallback updateCallback;
 
         if (_supportsBatchUpdates && update instanceof BatchUpdateScript) {
@@ -866,6 +868,8 @@
             updateCallback.close(false);
             throw e;
         }
+        
+        return updateCallback.getUpdateSummary();
     }
 
     protected boolean isSingleConnection() {
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDeleteBuilder.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDeleteBuilder.java
index e46cd19..fd12f0a 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDeleteBuilder.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDeleteBuilder.java
@@ -62,7 +62,7 @@
 
         logger.debug("Delete statement created: {}", sql);
         final boolean reuseStatement = !_inlineValues;
-        final PreparedStatement st = _updateCallback.getPreparedStatement(sql, reuseStatement);
+        final PreparedStatement st = _updateCallback.getPreparedStatement(sql, reuseStatement, false);
         try {
             if (reuseStatement) {
                 int valueCounter = 1;
@@ -75,7 +75,7 @@
                     }
                 }
             }
-            _updateCallback.executePreparedStatement(st, reuseStatement);
+            _updateCallback.executeDelete(st, reuseStatement);
         } catch (SQLException e) {
             throw JdbcUtils.wrapException(e, "execute delete statement: " + sql);
         } finally {
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDropTableBuilder.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDropTableBuilder.java
index e4f387b..87ae31d 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDropTableBuilder.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDropTableBuilder.java
@@ -46,9 +46,9 @@
     @Override
     public void execute() {
         final String sql = createSqlStatement();
-        final PreparedStatement statement = _updateCallback.getPreparedStatement(sql, false);
+        final PreparedStatement statement = _updateCallback.getPreparedStatement(sql, false, false);
         try {
-            _updateCallback.executePreparedStatement(statement, false);
+            _updateCallback.executePreparedStatement(statement, false, false);
 
             // remove the table reference from the schema
             final Schema schema = getTable().getSchema();
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcInsertBuilder.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcInsertBuilder.java
index d9c7a5e..d20b46c 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcInsertBuilder.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcInsertBuilder.java
@@ -66,7 +66,7 @@
 		}
 		final JdbcUpdateCallback updateCallback = getUpdateCallback();
 		final boolean reuseStatement = !_inlineValues;
-		final PreparedStatement st = updateCallback.getPreparedStatement(sql, reuseStatement);
+		final PreparedStatement st = updateCallback.getPreparedStatement(sql, reuseStatement, true);
 		try {
 			if (reuseStatement) {
 				Column[] columns = getColumns();
@@ -81,7 +81,7 @@
 					}
 				}
 			}
-			updateCallback.executePreparedStatement(st, reuseStatement);
+			updateCallback.executeInsert(st, reuseStatement);
 		} catch (SQLException e) {
 			throw JdbcUtils.wrapException(e, "execute insert statement: " + sql);
 		} finally {
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcSimpleUpdateCallback.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcSimpleUpdateCallback.java
index 3d44e42..6d174bf 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcSimpleUpdateCallback.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcSimpleUpdateCallback.java
@@ -34,14 +34,19 @@
     public JdbcSimpleUpdateCallback(JdbcDataContext dataContext) {
         super(dataContext);
     }
-    
+
     @Override
     protected void closePreparedStatement(PreparedStatement preparedStatement) {
         FileHelper.safeClose(preparedStatement);
     }
 
     @Override
-    protected void executePreparedStatement(PreparedStatement st) throws SQLException {
-        st.executeUpdate();
+    protected int executePreparedStatement(PreparedStatement st) throws SQLException {
+        return st.executeUpdate();
+    }
+    
+    @Override
+    protected boolean isGeneratedKeysCollectionEnabled() {
+        return true;
     }
 }
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUpdateBuilder.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUpdateBuilder.java
index 590a23d..4507ceb 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUpdateBuilder.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUpdateBuilder.java
@@ -62,7 +62,7 @@
         String sql = createSqlStatement();
         logger.debug("Update statement created: {}", sql);
         final boolean reuseStatement = !_inlineValues;
-        final PreparedStatement st = _updateCallback.getPreparedStatement(sql, reuseStatement);
+        final PreparedStatement st = _updateCallback.getPreparedStatement(sql, reuseStatement, false);
         try {
             if (reuseStatement) {
                 Column[] columns = getColumns();
@@ -90,7 +90,7 @@
                     }
                 }
             }
-            _updateCallback.executePreparedStatement(st, reuseStatement);
+            _updateCallback.executeUpdate(st, reuseStatement);
         } catch (SQLException e) {
             throw JdbcUtils.wrapException(e, "execute update statement: " + sql);
         } finally {
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUpdateCallback.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUpdateCallback.java
index a9db2fd..0ed231c 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUpdateCallback.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUpdateCallback.java
@@ -20,10 +20,15 @@
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.Statement;
 
 import org.apache.metamodel.AbstractUpdateCallback;
 import org.apache.metamodel.UpdateCallback;
+import org.apache.metamodel.UpdateSummary;
+import org.apache.metamodel.UpdateSummaryBuilder;
 import org.apache.metamodel.create.TableCreationBuilder;
 import org.apache.metamodel.delete.RowDeletionBuilder;
 import org.apache.metamodel.drop.TableDropBuilder;
@@ -31,6 +36,7 @@
 import org.apache.metamodel.schema.Schema;
 import org.apache.metamodel.schema.Table;
 import org.apache.metamodel.update.RowUpdationBuilder;
+import org.apache.metamodel.util.FileHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,32 +44,60 @@
 
     private static final Logger logger = LoggerFactory.getLogger(JdbcUpdateCallback.class);
 
-    private final JdbcDataContext _dataContext;
     private Connection _connection;
     private String _preparedStatementSql;
     private PreparedStatement _preparedStatement;
+    private final UpdateSummaryBuilder _updateSummaryBuilder;
 
     public JdbcUpdateCallback(JdbcDataContext dataContext) {
         super(dataContext);
-        _dataContext = dataContext;
+        _updateSummaryBuilder = new UpdateSummaryBuilder();
     }
 
+    protected final UpdateSummaryBuilder getUpdateSummaryBuilder() {
+        return _updateSummaryBuilder;
+    }
+    
+    protected abstract boolean isGeneratedKeysCollectionEnabled();
+
     protected abstract void closePreparedStatement(PreparedStatement preparedStatement);
 
-    protected abstract void executePreparedStatement(PreparedStatement preparedStatement) throws SQLException;
+    protected abstract int executePreparedStatement(PreparedStatement preparedStatement) throws SQLException;
 
-    public void executePreparedStatement(PreparedStatement preparedStatement, boolean reusedStatement)
-            throws SQLException {
-        executePreparedStatement(preparedStatement);
+    public int executePreparedStatement(PreparedStatement preparedStatement, boolean reusedStatement,
+            boolean collectGeneratedKeys) throws SQLException {
+        final int result = executePreparedStatement(preparedStatement);
+
+        if (collectGeneratedKeys && isGeneratedKeysCollectionEnabled()) {
+            try {
+                final ResultSet generatedKeysResultSet = preparedStatement.getGeneratedKeys();
+                try {
+                    while (generatedKeysResultSet.next()) {
+                        final Object key = generatedKeysResultSet.getObject(1);
+                        getUpdateSummaryBuilder().addGeneratedKey(key);
+                    }
+                } finally {
+                    FileHelper.safeClose(generatedKeysResultSet);
+                }
+            } catch (SQLFeatureNotSupportedException e) {
+                // ignore
+                logger.debug("Getting generated keys from JDBC statement is not supported by driver: {}", e
+                        .getMessage(), e);
+            } catch (SQLException | RuntimeException e) {
+                logger.warn("Failed to get generated keys from JDBC statement: {}", e.getMessage(), e);
+            }
+        }
+
         if (!reusedStatement) {
             closePreparedStatement(preparedStatement);
         }
+        return result;
     }
 
     protected final Connection getConnection() {
         if (_connection == null) {
             _connection = getDataContext().getConnection();
-            if (_dataContext.getQueryRewriter().isTransactional()) {
+            if (getDataContext().getQueryRewriter().isTransactional()) {
                 try {
                     _connection.setAutoCommit(false);
                 } catch (SQLException e) {
@@ -80,11 +114,11 @@
                 closePreparedStatement(_preparedStatement);
             }
 
-            if (_dataContext.getQueryRewriter().isTransactional()) {
+            if (getDataContext().getQueryRewriter().isTransactional()) {
                 try {
                     commitOrRollback(success);
 
-                    if (_dataContext.isDefaultAutoCommit()) {
+                    if (getDataContext().isDefaultAutoCommit()) {
                         try {
                             getConnection().setAutoCommit(true);
                         } catch (SQLException e) {
@@ -122,19 +156,20 @@
 
     @Override
     public final RowInsertionBuilder insertInto(Table table) throws IllegalArgumentException, IllegalStateException {
-        return new JdbcInsertBuilder(this, table, _dataContext.getQueryRewriter());
+        return new JdbcInsertBuilder(this, table, getDataContext().getQueryRewriter());
     }
 
+    // override the return type to the more specific subtype.
     @Override
     public final JdbcDataContext getDataContext() {
-        return _dataContext;
+        return (JdbcDataContext) super.getDataContext();
     }
 
     protected String quoteIfNescesary(String identifier) {
         if (identifier == null) {
             return null;
         }
-        final String quote = _dataContext.getIdentifierQuoteString();
+        final String quote = getDataContext().getIdentifierQuoteString();
         if (quote == null) {
             return identifier;
         }
@@ -153,7 +188,8 @@
         return identifier;
     }
 
-    public final PreparedStatement getPreparedStatement(String sql, boolean reuseStatement) {
+    public final PreparedStatement getPreparedStatement(String sql, boolean reuseStatement,
+            boolean returnGeneratedKeys) {
         final PreparedStatement preparedStatement;
         if (reuseStatement) {
             if (sql.equals(_preparedStatementSql)) {
@@ -167,20 +203,27 @@
                         throw e;
                     }
                 }
-                preparedStatement = createPreparedStatement(sql);
+                preparedStatement = createPreparedStatement(sql, returnGeneratedKeys);
                 _preparedStatement = preparedStatement;
                 _preparedStatementSql = sql;
             }
         } else {
-            preparedStatement = createPreparedStatement(sql);
+            preparedStatement = createPreparedStatement(sql, returnGeneratedKeys);
         }
         return preparedStatement;
     }
-
-    private final PreparedStatement createPreparedStatement(String sql) {
+    
+    private final PreparedStatement createPreparedStatement(String sql, boolean returnGeneratedKeys) {
         try {
+            if (returnGeneratedKeys && isGeneratedKeysCollectionEnabled()) {
+                return getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+            }
             return getConnection().prepareStatement(sql);
         } catch (SQLException e) {
+            if (returnGeneratedKeys) {
+                // not all databases support the RETURN_GENERATED_KEYS flag, so retry without
+                return createPreparedStatement(sql, false);
+            }
             throw JdbcUtils.wrapException(e, "create prepared statement for: " + sql);
         }
     }
@@ -191,9 +234,9 @@
     }
 
     @Override
-    public RowDeletionBuilder deleteFrom(Table table) throws IllegalArgumentException, IllegalStateException,
+    public final RowDeletionBuilder deleteFrom(Table table) throws IllegalArgumentException, IllegalStateException,
             UnsupportedOperationException {
-        return new JdbcDeleteBuilder(this, table, _dataContext.getQueryRewriter());
+        return new JdbcDeleteBuilder(this, table, getDataContext().getQueryRewriter());
     }
 
     @Override
@@ -204,7 +247,7 @@
     @Override
     public TableDropBuilder dropTable(Table table) throws IllegalArgumentException, IllegalStateException,
             UnsupportedOperationException {
-        return new JdbcDropTableBuilder(this, table, _dataContext.getQueryRewriter());
+        return new JdbcDropTableBuilder(this, table, getDataContext().getQueryRewriter());
     }
 
     @Override
@@ -213,8 +256,29 @@
     }
 
     @Override
-    public RowUpdationBuilder update(Table table) throws IllegalArgumentException, IllegalStateException,
+    public final RowUpdationBuilder update(Table table) throws IllegalArgumentException, IllegalStateException,
             UnsupportedOperationException {
-        return new JdbcUpdateBuilder(this, table, _dataContext.getQueryRewriter());
+        return new JdbcUpdateBuilder(this, table, getDataContext().getQueryRewriter());
     }
+
+    public void executeInsert(PreparedStatement st, boolean reuseStatement) throws SQLException {
+        executePreparedStatement(st, reuseStatement, true);
+        _updateSummaryBuilder.addInsert();
+    }
+
+    public void executeUpdate(PreparedStatement st, boolean reuseStatement) throws SQLException {
+        final int updates = executePreparedStatement(st, reuseStatement, false);
+        _updateSummaryBuilder.addUpdates(updates);
+    }
+
+    public void executeDelete(PreparedStatement st, boolean reuseStatement) throws SQLException {
+        final int deletes = executePreparedStatement(st, reuseStatement, false);
+        _updateSummaryBuilder.addDeletes(deletes);
+    }
+
+    @Override
+    public UpdateSummary getUpdateSummary() {
+        return _updateSummaryBuilder.build();
+    }
+
 }
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/OracleQueryRewriter.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/OracleQueryRewriter.java
index 647035e..f3108fb 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/OracleQueryRewriter.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/OracleQueryRewriter.java
@@ -18,8 +18,6 @@
  */
 package org.apache.metamodel.jdbc.dialects;
 
-import static org.apache.metamodel.jdbc.JdbcDataContext.DATABASE_PRODUCT_ORACLE;
-
 import org.apache.metamodel.jdbc.JdbcDataContext;
 import org.apache.metamodel.query.FilterItem;
 import org.apache.metamodel.schema.ColumnType;
diff --git a/jdbc/src/test/java/org/apache/metamodel/dialects/SQLServerQueryRewriterTest.java b/jdbc/src/test/java/org/apache/metamodel/dialects/SQLServerQueryRewriterTest.java
index 86f9828..d01e603 100644
--- a/jdbc/src/test/java/org/apache/metamodel/dialects/SQLServerQueryRewriterTest.java
+++ b/jdbc/src/test/java/org/apache/metamodel/dialects/SQLServerQueryRewriterTest.java
@@ -20,11 +20,6 @@
 
 import static org.apache.metamodel.jdbc.JdbcDataContext.DATABASE_PRODUCT_SQLSERVER;
 
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-
-import junit.framework.TestCase;
-
 import org.apache.metamodel.jdbc.JdbcDataContext;
 import org.apache.metamodel.jdbc.dialects.SQLServerQueryRewriter;
 import org.apache.metamodel.query.FilterItem;
@@ -39,6 +34,8 @@
 import org.apache.metamodel.util.TimeComparator;
 import org.easymock.EasyMock;
 
+import junit.framework.TestCase;
+
 public class SQLServerQueryRewriterTest extends TestCase {
 
     private MutableTable table;
diff --git a/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcTestTemplates.java b/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcTestTemplates.java
index f216a75..0f6d82d 100644
--- a/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcTestTemplates.java
+++ b/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcTestTemplates.java
@@ -40,6 +40,7 @@
 import org.apache.metamodel.BatchUpdateScript;
 import org.apache.metamodel.UpdateCallback;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.create.ColumnCreationBuilder;
 import org.apache.metamodel.create.CreateTable;
 import org.apache.metamodel.create.TableCreationBuilder;
@@ -73,7 +74,7 @@
 
         final Map<Object, Object> map = new HashMap<Object, Object>();
         try {
-            dc.executeUpdate(new UpdateScript() {
+            final UpdateSummary summary = dc.executeUpdate(new UpdateScript() {
                 @Override
                 public void run(UpdateCallback cb) {
                     ColumnCreationBuilder createTableBuilder = cb.createTable(schema, "test_table").withColumn("id")
@@ -86,6 +87,7 @@
                     cb.insertInto(table).value("id", 4.0).value("code", "C02").execute();
                 }
             });
+            assertEquals(4, summary.getInsertedRows().get().intValue());
 
             assertEquals(1, getCount(dc.query().from("test_table").selectCount().where("code").isNull().execute()));
             assertEquals(3, getCount(dc.query().from("test_table").selectCount().where("code").isNotNull().execute()));
@@ -355,12 +357,15 @@
         assertFalse(ds.next());
         ds.close();
 
-        dc.executeUpdate(new UpdateScript() {
+        final UpdateSummary updateSummary = dc.executeUpdate(new UpdateScript() {
             @Override
             public void run(UpdateCallback callback) {
                 callback.deleteFrom("test_table").where("id").in(Arrays.<String> asList("1", "2")).execute();
             }
         });
+        assertEquals(2, updateSummary.getDeletedRows().get().intValue());
+        assertEquals(0, updateSummary.getUpdatedRows().get().intValue());
+        assertEquals(0, updateSummary.getInsertedRows().get().intValue());
 
         ds = dc.query().from("test_table").selectCount().where("id").eq(2).or("id").eq(1).execute();
         assertTrue(ds.next());
@@ -453,7 +458,7 @@
             assertFalse(ds.next());
             ds.close();
 
-            dc.executeUpdate(new UpdateScript() {
+            final UpdateSummary updateSummary = dc.executeUpdate(new UpdateScript() {
                 @Override
                 public void run(UpdateCallback callback) {
                     // update record 1
@@ -470,6 +475,9 @@
                             .where("birthdate").isEquals(DateUtils.get(1982, Month.APRIL, 20)).execute();
                 }
             });
+            assertEquals(0, updateSummary.getInsertedRows().get().intValue());
+            assertEquals(0, updateSummary.getDeletedRows().get().intValue());
+            assertEquals(1, updateSummary.getUpdatedRows().get().intValue());
 
             ds = dc.query().from(schema.getTableByName(tableName)).select("id", "birthdate", "wakemeup").orderBy("id")
                     .execute();
diff --git a/jdbc/src/test/java/org/apache/metamodel/jdbc/dialects/OracleQueryRewriterTest.java b/jdbc/src/test/java/org/apache/metamodel/jdbc/dialects/OracleQueryRewriterTest.java
index a36a4ba..a1a141a 100644
--- a/jdbc/src/test/java/org/apache/metamodel/jdbc/dialects/OracleQueryRewriterTest.java
+++ b/jdbc/src/test/java/org/apache/metamodel/jdbc/dialects/OracleQueryRewriterTest.java
@@ -21,8 +21,6 @@
 import static org.apache.metamodel.jdbc.JdbcDataContext.DATABASE_PRODUCT_ORACLE;
 import static org.junit.Assert.assertEquals;
 
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
 import org.apache.metamodel.jdbc.JdbcDataContext;
diff --git a/jdbc/src/test/java/org/apache/metamodel/jdbc/integrationtests/PostgresqlTest.java b/jdbc/src/test/java/org/apache/metamodel/jdbc/integrationtests/PostgresqlTest.java
index 2668df9..6f8fb09 100644
--- a/jdbc/src/test/java/org/apache/metamodel/jdbc/integrationtests/PostgresqlTest.java
+++ b/jdbc/src/test/java/org/apache/metamodel/jdbc/integrationtests/PostgresqlTest.java
@@ -24,6 +24,7 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Optional;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
@@ -33,8 +34,10 @@
 import org.apache.metamodel.DataContext;
 import org.apache.metamodel.UpdateCallback;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.DataSetTableModel;
+import org.apache.metamodel.drop.DropTable;
 import org.apache.metamodel.insert.RowInsertionBuilder;
 import org.apache.metamodel.jdbc.JdbcDataContext;
 import org.apache.metamodel.jdbc.JdbcTestTemplates;
@@ -478,6 +481,42 @@
         }
     }
 
+    public void testGetGeneratedKeys() throws Exception {
+        if (!isConfigured()) {
+            return;
+        }
+
+        final JdbcDataContext dc = new JdbcDataContext(getConnection());
+        final Schema schema = dc.getDefaultSchema();
+        final String tableName = "my_table_with_generated_keys";
+        
+        if (schema.getTableByName(tableName) != null) {
+            dc.executeUpdate(new DropTable(schema, tableName));
+        }
+
+        final UpdateSummary updateSummary = dc.executeUpdate(new UpdateScript() {
+            @Override
+            public void run(UpdateCallback cb) {
+                Table table = cb.createTable(schema, tableName).withColumn("id").ofType(ColumnType.INTEGER)
+                        .ofNativeType("SERIAL").nullable(false).asPrimaryKey().withColumn("foo").ofType(
+                                ColumnType.STRING).execute();
+                assertEquals(tableName, table.getName());
+
+                cb.insertInto(table).value("foo", "hello").execute();
+                cb.insertInto(table).value("foo", "world").execute();
+            }
+        });
+
+        final Optional<Integer> insertedRows = updateSummary.getInsertedRows();
+        assertTrue(insertedRows.isPresent());
+        assertEquals(2, insertedRows.get().intValue());
+        
+        final Optional<Iterable<Object>> generatedKeys = updateSummary.getGeneratedKeys();
+        assertTrue(generatedKeys.isPresent());
+        assertEquals("[1, 2]", generatedKeys.get().toString());
+        
+    }
+
     public void testBlob() throws Exception {
         if (!isConfigured()) {
             return;
diff --git a/json/pom.xml b/json/pom.xml
index 943dc03..9607056 100644
--- a/json/pom.xml
+++ b/json/pom.xml
@@ -13,7 +13,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-json</artifactId>
diff --git a/mongodb/common/pom.xml b/mongodb/common/pom.xml
index 9916ceb..9675d9e 100644
--- a/mongodb/common/pom.xml
+++ b/mongodb/common/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel-mongodb</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-mongodb-common</artifactId>
diff --git a/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDbTableDef.java b/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDbTableDef.java
deleted file mode 100644
index 7805b53..0000000
--- a/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDbTableDef.java
+++ /dev/null
@@ -1,46 +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.metamodel.mongodb.common;
-
-import java.io.Serializable;
-
-import org.apache.metamodel.schema.ColumnType;
-import org.apache.metamodel.util.SimpleTableDef;
-
-/**
- * Defines a table layout for MongoDB tables. This class can
- * be used as an instruction set for the MongoDB DataContext implementations to specify
- * which collections, which columns (and their types) should be included in the
- * schema structure of a Mongo DB database.
- * 
- * @deprecated use {@link SimpleTableDef} instead.
- */
-@Deprecated
-public final class MongoDbTableDef extends SimpleTableDef implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    public MongoDbTableDef(String name, String[] columnNames, ColumnType[] columnTypes) {
-        super(name, columnNames, columnTypes);
-    }
-
-    public MongoDbTableDef(String name, String[] columnNames) {
-        super(name, columnNames);
-    }
-}
\ No newline at end of file
diff --git a/mongodb/mongo2/pom.xml b/mongodb/mongo2/pom.xml
index a81060b..8cd2540 100644
--- a/mongodb/mongo2/pom.xml
+++ b/mongodb/mongo2/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel-mongodb</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-mongodb-mongo2</artifactId>
diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataContext.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataContext.java
index 535c8f8..84ae8db 100644
--- a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataContext.java
+++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataContext.java
@@ -31,6 +31,7 @@
 import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.QueryPostprocessDataContext;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.DataSetHeader;
@@ -38,7 +39,6 @@
 import org.apache.metamodel.data.Row;
 import org.apache.metamodel.data.SimpleDataSetHeader;
 import org.apache.metamodel.mongodb.common.MongoDBUtils;
-import org.apache.metamodel.mongodb.common.MongoDbTableDef;
 import org.apache.metamodel.query.FilterItem;
 import org.apache.metamodel.query.FromItem;
 import org.apache.metamodel.query.OperatorType;
@@ -83,17 +83,6 @@
     private Schema _schema;
 
     /**
-     * Constructor available for backwards compatibility
-     *
-     * @deprecated use {@link #MongoDbDataContext(DB, SimpleTableDef...)}
-     *             instead
-     */
-    @Deprecated
-    public MongoDbDataContext(DB mongoDb, MongoDbTableDef... tableDefs) {
-        this(mongoDb, (SimpleTableDef[]) tableDefs);
-    }
-
-    /**
      * Constructs a {@link MongoDbDataContext}. This constructor accepts a
      * custom array of {@link MongoDbTableDef}s which allows the user to define
      * his own view on the collections in the database.
@@ -287,9 +276,7 @@
                 // "SELECT [columns] FROM [table] WHERE [conditions]"
                 // query.
                 for (SelectItem selectItem : selectItems) {
-                    if (selectItem.getAggregateFunction() != null
-                            || selectItem.getScalarFunction() != null
-                                    || selectItem.getColumn() == null) {
+                    if (selectItem.hasFunction() || selectItem.getColumn() == null) {
                         allSelectItemsAreColumns = false;
                         break;
                     }
@@ -503,25 +490,26 @@
     /**
      * Executes an update with a specific {@link WriteConcernAdvisor}.
      */
-    public void executeUpdate(UpdateScript update, WriteConcernAdvisor writeConcernAdvisor) {
+    public UpdateSummary executeUpdate(UpdateScript update, WriteConcernAdvisor writeConcernAdvisor) {
         MongoDbUpdateCallback callback = new MongoDbUpdateCallback(this, writeConcernAdvisor);
         try {
             update.run(callback);
         } finally {
             callback.close();
         }
+        return callback.getUpdateSummary();
     }
 
     /**
      * Executes an update with a specific {@link WriteConcern}.
      */
-    public void executeUpdate(UpdateScript update, WriteConcern writeConcern) {
-        executeUpdate(update, new SimpleWriteConcernAdvisor(writeConcern));
+    public UpdateSummary executeUpdate(UpdateScript update, WriteConcern writeConcern) {
+        return executeUpdate(update, new SimpleWriteConcernAdvisor(writeConcern));
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
-        executeUpdate(update, getWriteConcernAdvisor());
+    public UpdateSummary executeUpdate(UpdateScript update) {
+        return executeUpdate(update, getWriteConcernAdvisor());
     }
 
     /**
diff --git a/mongodb/mongo3/pom.xml b/mongodb/mongo3/pom.xml
index 8f8380f..4ff4fd7 100644
--- a/mongodb/mongo3/pom.xml
+++ b/mongodb/mongo3/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel-mongodb</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-mongodb-mongo3</artifactId>
diff --git a/mongodb/mongo3/src/main/java/org/apache/metamodel/mongodb/mongo3/MongoDbDataContext.java b/mongodb/mongo3/src/main/java/org/apache/metamodel/mongodb/mongo3/MongoDbDataContext.java
index 3108964..ddb18d5 100644
--- a/mongodb/mongo3/src/main/java/org/apache/metamodel/mongodb/mongo3/MongoDbDataContext.java
+++ b/mongodb/mongo3/src/main/java/org/apache/metamodel/mongodb/mongo3/MongoDbDataContext.java
@@ -32,6 +32,7 @@
 import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.QueryPostprocessDataContext;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.DataSetHeader;
@@ -275,9 +276,7 @@
                 // "SELECT [columns] FROM [table] WHERE [conditions]"
                 // query.
                 for (SelectItem selectItem : selectItems) {
-                    if (selectItem.getAggregateFunction() != null
-                            || selectItem.getScalarFunction() != null
-                                    || selectItem.getColumn() == null) {
+                    if (selectItem.hasFunction() || selectItem.getColumn() == null) {
                         allSelectItemsAreColumns = false;
                         break;
                     }
@@ -520,25 +519,26 @@
     /**
      * Executes an update with a specific {@link WriteConcernAdvisor}.
      */
-    public void executeUpdate(UpdateScript update, WriteConcernAdvisor writeConcernAdvisor) {
+    public UpdateSummary executeUpdate(UpdateScript update, WriteConcernAdvisor writeConcernAdvisor) {
         MongoDbUpdateCallback callback = new MongoDbUpdateCallback(this, writeConcernAdvisor);
         try {
             update.run(callback);
         } finally {
             callback.close();
         }
+        return callback.getUpdateSummary();
     }
 
     /**
      * Executes an update with a specific {@link WriteConcern}.
      */
-    public void executeUpdate(UpdateScript update, WriteConcern writeConcern) {
-        executeUpdate(update, new SimpleWriteConcernAdvisor(writeConcern));
+    public UpdateSummary executeUpdate(UpdateScript update, WriteConcern writeConcern) {
+        return executeUpdate(update, new SimpleWriteConcernAdvisor(writeConcern));
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
-        executeUpdate(update, getWriteConcernAdvisor());
+    public UpdateSummary executeUpdate(UpdateScript update) {
+        return executeUpdate(update, getWriteConcernAdvisor());
     }
 
     /**
diff --git a/mongodb/pom.xml b/mongodb/pom.xml
index 0d0c2da..77b5375 100644
--- a/mongodb/pom.xml
+++ b/mongodb/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-mongodb</artifactId>
diff --git a/neo4j/pom.xml b/neo4j/pom.xml
index 3d38fa8..d355e98 100644
--- a/neo4j/pom.xml
+++ b/neo4j/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-neo4j</artifactId>
diff --git a/openoffice/pom.xml b/openoffice/pom.xml
index 28e8ed8..8b5c76f 100644
--- a/openoffice/pom.xml
+++ b/openoffice/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-openoffice</artifactId>
diff --git a/pojo/pom.xml b/pojo/pom.xml
index ed9472a..02814b6 100644
--- a/pojo/pom.xml
+++ b/pojo/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-pojo</artifactId>
diff --git a/pojo/src/main/java/org/apache/metamodel/pojo/PojoDataContext.java b/pojo/src/main/java/org/apache/metamodel/pojo/PojoDataContext.java
index 2de3d59..9369e96 100644
--- a/pojo/src/main/java/org/apache/metamodel/pojo/PojoDataContext.java
+++ b/pojo/src/main/java/org/apache/metamodel/pojo/PojoDataContext.java
@@ -30,6 +30,7 @@
 import org.apache.metamodel.MetaModelHelper;
 import org.apache.metamodel.QueryPostprocessDataContext;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.MaxRowsDataSet;
@@ -140,11 +141,12 @@
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
-        PojoUpdateCallback updateCallback = new PojoUpdateCallback(this);
+    public UpdateSummary executeUpdate(UpdateScript update) {
+        final PojoUpdateCallback updateCallback = new PojoUpdateCallback(this);
         synchronized (this) {
             update.run(updateCallback);
         }
+        return updateCallback.getUpdateSummary();
     }
 
     protected void addTableDataProvider(TableDataProvider<?> tableDataProvider) {
diff --git a/pom.xml b/pom.xml
index 65fa153..50f5674 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,11 +42,11 @@
 		<url>https://git-wip-us.apache.org/repos/asf?p=metamodel.git</url>
 		<connection>scm:git:http://git-wip-us.apache.org/repos/asf/metamodel.git</connection>
 		<developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/metamodel.git</developerConnection>
-		<tag>HEAD</tag>
+		<tag>5.x</tag>
 	</scm>
 	<groupId>org.apache.metamodel</groupId>
 	<artifactId>MetaModel</artifactId>
-	<version>4.6.1-SNAPSHOT</version>
+	<version>5.0-SNAPSHOT</version>
 	<name>MetaModel</name>
 	<description>MetaModel is a library that encapsulates the differences and enhances 
 		the capabilities of different datastores. Rich querying abilities are
@@ -167,12 +167,12 @@
 	<build>
 		<plugins>
 			<plugin>
-				<!-- Ensures java 7 compatibility -->
+				<!-- Ensures java 8 compatibility -->
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-compiler-plugin</artifactId>
 				<configuration>
-					<source>1.7</source>
-					<target>1.7</target>
+					<source>1.8</source>
+					<target>1.8</target>
 					<encoding>utf-8</encoding>
 				</configuration>
 			</plugin>
@@ -251,6 +251,7 @@
 				</executions>
 				<configuration>
 					<excludePackageNames>com.sugarcrm.ws.soap</excludePackageNames>
+					<additionalparam>-Xdoclint:none</additionalparam>
 				</configuration>
 			</plugin>
 			<plugin>
diff --git a/salesforce/pom.xml b/salesforce/pom.xml
index 32dee0c..871c173 100644
--- a/salesforce/pom.xml
+++ b/salesforce/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-salesforce</artifactId>
diff --git a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceDataContext.java b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceDataContext.java
index 3076147..37467b7 100644
--- a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceDataContext.java
+++ b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceDataContext.java
@@ -25,9 +25,11 @@
 import java.util.TimeZone;
 
 import com.sforce.ws.ConnectorConfig;
+
 import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.QueryPostprocessDataContext;
 import org.apache.metamodel.UpdateScript;
+import org.apache.metamodel.UpdateSummary;
 import org.apache.metamodel.UpdateableDataContext;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.FirstRowDataSet;
@@ -353,8 +355,9 @@
         }
     }
 
+    @SuppressWarnings("deprecation")
     private static void validateSoqlSupportedSelectItem(SelectItem selectItem) throws UnsupportedOperationException {
-        if (selectItem.getFunction() != null) {
+        if (selectItem.hasFunction()) {
             throw new UnsupportedOperationException("Function select items not supported: " + selectItem);
         }
         if (selectItem.getSubQuerySelectItem() != null) {
@@ -394,9 +397,10 @@
     }
 
     @Override
-    public void executeUpdate(UpdateScript update) {
+    public UpdateSummary executeUpdate(UpdateScript update) {
         final SalesforceUpdateCallback callback = new SalesforceUpdateCallback(this, _connection);
         update.run(callback);
         callback.close();
+        return callback.getUpdateSummary();
     }
 }
diff --git a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceSchema.java b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceSchema.java
index 90e5a66..d5f70c9 100644
--- a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceSchema.java
+++ b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceSchema.java
@@ -20,11 +20,11 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Supplier;
 
 import org.apache.metamodel.schema.AbstractSchema;
 import org.apache.metamodel.schema.Table;
 import org.apache.metamodel.util.LazyRef;
-import org.apache.metamodel.util.Ref;
 
 import com.sforce.soap.partner.DescribeGlobalResult;
 import com.sforce.soap.partner.DescribeGlobalSObjectResult;
@@ -40,7 +40,7 @@
     private static final long serialVersionUID = 1L;
 
     private final String _name;
-    private final transient Ref<List<Table>> _tableRef;
+    private final transient Supplier<List<Table>> _tableRef;
     private final transient PartnerConnection _connection;
 
     public SalesforceSchema(String name, PartnerConnection connection) {
diff --git a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceTable.java b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceTable.java
index 0c1c113..5db2b47 100644
--- a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceTable.java
+++ b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceTable.java
@@ -20,6 +20,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Supplier;
 
 import org.apache.metamodel.schema.AbstractTable;
 import org.apache.metamodel.schema.Column;
@@ -29,7 +30,6 @@
 import org.apache.metamodel.schema.Schema;
 import org.apache.metamodel.schema.TableType;
 import org.apache.metamodel.util.LazyRef;
-import org.apache.metamodel.util.Ref;
 
 import com.sforce.soap.partner.DescribeSObjectResult;
 import com.sforce.soap.partner.Field;
@@ -45,7 +45,7 @@
 
     private static final long serialVersionUID = 1L;
 
-    private final transient Ref<List<Column>> _columnRef;
+    private final transient Supplier<List<Column>> _columnRef;
     private final transient PartnerConnection _connection;
     private final String _name;
     private final String _remarks;
diff --git a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceUpdateCallback.java b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceUpdateCallback.java
index 757cb95..bf9b43b 100644
--- a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceUpdateCallback.java
+++ b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceUpdateCallback.java
@@ -215,6 +215,7 @@
      * @param idList
      * @param whereItem
      */
+    @SuppressWarnings("deprecation")
     protected void buildIdList(List<String> idList, FilterItem whereItem) {
         if (whereItem.isCompoundFilter()) {
             final LogicalOperator logicalOperator = whereItem.getLogicalOperator();
@@ -244,7 +245,7 @@
 
         final Object operand = whereItem.getOperand();
 
-        if (column == null || operand == null || selectItem.getFunction() != null) {
+        if (column == null || operand == null || selectItem.hasFunction()) {
             throw new IllegalStateException(
                     "Salesforce only allows deletion of records by their specific IDs. Violated by where item: "
                             + whereItem);
diff --git a/spring/pom.xml b/spring/pom.xml
index aa97520..6792582 100644
--- a/spring/pom.xml
+++ b/spring/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-spring</artifactId>
diff --git a/sugarcrm/pom.xml b/sugarcrm/pom.xml
index db4c9bf..e423e36 100644
--- a/sugarcrm/pom.xml
+++ b/sugarcrm/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-sugarcrm</artifactId>
diff --git a/sugarcrm/src/main/java/org/apache/metamodel/sugarcrm/SugarCrmSchema.java b/sugarcrm/src/main/java/org/apache/metamodel/sugarcrm/SugarCrmSchema.java
index 35f98ab..49e24e7 100644
--- a/sugarcrm/src/main/java/org/apache/metamodel/sugarcrm/SugarCrmSchema.java
+++ b/sugarcrm/src/main/java/org/apache/metamodel/sugarcrm/SugarCrmSchema.java
@@ -20,10 +20,10 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Supplier;
 
 import org.apache.metamodel.schema.AbstractSchema;
 import org.apache.metamodel.schema.Table;
-import org.apache.metamodel.util.Ref;
 
 import com.sugarcrm.ws.soap.SugarsoapPortType;
 
@@ -34,7 +34,7 @@
     private final List<Table> _tables;
     private final String _name;
 
-    public SugarCrmSchema(String name, SugarsoapPortType service, Ref<String> sessionId) {
+    public SugarCrmSchema(String name, SugarsoapPortType service, Supplier<String> sessionId) {
         _name = name;
         _tables = new ArrayList<Table>();
         _tables.add(new SugarCrmTable("Accounts", this, service, sessionId));
diff --git a/sugarcrm/src/main/java/org/apache/metamodel/sugarcrm/SugarCrmTable.java b/sugarcrm/src/main/java/org/apache/metamodel/sugarcrm/SugarCrmTable.java
index 1cb965e..1926d83 100644
--- a/sugarcrm/src/main/java/org/apache/metamodel/sugarcrm/SugarCrmTable.java
+++ b/sugarcrm/src/main/java/org/apache/metamodel/sugarcrm/SugarCrmTable.java
@@ -22,6 +22,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Supplier;
 
 import org.apache.metamodel.schema.AbstractTable;
 import org.apache.metamodel.schema.Column;
@@ -31,7 +32,6 @@
 import org.apache.metamodel.schema.Schema;
 import org.apache.metamodel.schema.TableType;
 import org.apache.metamodel.util.LazyRef;
-import org.apache.metamodel.util.Ref;
 import org.w3c.dom.Node;
 
 import com.sugarcrm.ws.soap.FieldList;
@@ -79,9 +79,9 @@
 
     private final String _name;
     private final Schema _schema;
-    private final Ref<List<Column>> _columnsRef;
+    private final Supplier<List<Column>> _columnsRef;
 
-    public SugarCrmTable(String name, Schema schema, final SugarsoapPortType service, final Ref<String> sessionId) {
+    public SugarCrmTable(String name, Schema schema, final SugarsoapPortType service, final Supplier<String> sessionId) {
         _name = name;
         _schema = schema;
         _columnsRef = new LazyRef<List<Column>>() {
diff --git a/xml/pom.xml b/xml/pom.xml
index df80435..be5f057 100644
--- a/xml/pom.xml
+++ b/xml/pom.xml
@@ -21,7 +21,7 @@
 	<parent>
 		<artifactId>MetaModel</artifactId>
 		<groupId>org.apache.metamodel</groupId>
-		<version>4.6.1-SNAPSHOT</version>
+		<version>5.0-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>MetaModel-xml</artifactId>
diff --git a/xml/src/main/java/org/apache/metamodel/xml/XmlDataContext.java b/xml/src/main/java/org/apache/metamodel/xml/XmlDataContext.java
deleted file mode 100644
index c03c24d..0000000
--- a/xml/src/main/java/org/apache/metamodel/xml/XmlDataContext.java
+++ /dev/null
@@ -1,59 +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.metamodel.xml;
-
-import java.io.File;
-import java.net.URL;
-
-import org.w3c.dom.Document;
-import org.xml.sax.InputSource;
-
-/**
- * DataContext implementation for XML files.
- * 
- * @deprecated use {@link XmlDomDataContext} or {@link XmlSaxDataContext}
- *             instead.
- */
-@Deprecated
-public final class XmlDataContext extends XmlDomDataContext {
-
-	public XmlDataContext(File file, boolean autoFlattenTables)
-			throws IllegalArgumentException {
-		super(file, autoFlattenTables);
-	}
-
-	public XmlDataContext(File file) {
-		super(file);
-	}
-
-	public XmlDataContext(InputSource inputSource, String schemaName,
-			boolean autoFlattenTables) {
-		super(inputSource, schemaName, autoFlattenTables);
-	}
-
-	public XmlDataContext(String schemaName, Document document,
-			boolean autoFlattenTables) {
-		super(schemaName, document, autoFlattenTables);
-	}
-
-	public XmlDataContext(URL url, boolean autoFlattenTables)
-			throws IllegalArgumentException {
-		super(url, autoFlattenTables);
-	}
-}
diff --git a/xml/src/main/java/org/apache/metamodel/xml/XmlDomDataContext.java b/xml/src/main/java/org/apache/metamodel/xml/XmlDomDataContext.java
index c71d8ca..b9936af 100644
--- a/xml/src/main/java/org/apache/metamodel/xml/XmlDomDataContext.java
+++ b/xml/src/main/java/org/apache/metamodel/xml/XmlDomDataContext.java
@@ -27,6 +27,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.function.Supplier;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -57,7 +58,6 @@
 import org.apache.metamodel.util.FileResource;
 import org.apache.metamodel.util.ImmutableRef;
 import org.apache.metamodel.util.NumberComparator;
-import org.apache.metamodel.util.Ref;
 import org.apache.metamodel.util.Resource;
 import org.apache.metamodel.util.UrlResource;
 import org.slf4j.Logger;
@@ -97,7 +97,7 @@
 
     private static final String TEXT_CONTENT_TEMP_SUFFIX = "_metamodel_text_content";
 
-    private final Ref<InputSource> _inputSourceRef;
+    private final Supplier<InputSource> _inputSourceRef;
     private final Map<String, List<Object[]>> _tableData = new HashMap<String, List<Object[]>>();;
     private final String _schemaName;
 
@@ -152,13 +152,10 @@
         this(new UrlResource(url), autoFlattenTables);
     }
 
-    private static Ref<InputSource> createInputSourceRef(final Resource resource) {
-        return new Ref<InputSource>() {
-            @Override
-            public InputSource get() {
+    private static Supplier<InputSource> createInputSourceRef(final Resource resource) {
+        return () -> {
                 final InputStream in = resource.read();
                 return new InputSource(in);
-            }
         };
     }
 
@@ -294,7 +291,8 @@
                     // Rename all text content columns to reasonable
                     // names (preferably element node name)
                     String currentName = textContentColumn.getName();
-                    String preferredName = currentName.substring(0, currentName.length() - TEXT_CONTENT_TEMP_SUFFIX.length());
+                    String preferredName = currentName.substring(0, currentName.length() - TEXT_CONTENT_TEMP_SUFFIX
+                            .length());
                     column = (MutableColumn) table.getColumnByName(preferredName);
                     if (column == null) {
                         textContentColumn.setName(preferredName);
@@ -327,12 +325,13 @@
 
                 if (parentKeyColumn != null) {
                     Table parentTable = parentKeyColumn.getTable();
-                    foreignKeyColumn = new MutableColumn(parentTable.getName() + "_id", parentKeyColumn.getType(), table,
-                            table.getColumnCount(), false);
+                    foreignKeyColumn = new MutableColumn(parentTable.getName() + "_id", parentKeyColumn.getType(),
+                            table, table.getColumnCount(), false);
                     foreignKeyColumn.setNativeType(NATIVE_TYPE_FOREIGN_KEY);
                     table.addColumn(foreignKeyColumn);
 
-                    MutableRelationship.createRelationship(new Column[] { parentKeyColumn }, new Column[] { foreignKeyColumn });
+                    MutableRelationship.createRelationship(new Column[] { parentKeyColumn }, new Column[] {
+                            foreignKeyColumn });
 
                 } else {
                     foreignKeyColumn = null;
@@ -412,8 +411,8 @@
         }
         if (column == null && preferredColumnName != null) {
             logger.info("Creating text content column for table: " + table.getName());
-            column = new MutableColumn(preferredColumnName + TEXT_CONTENT_TEMP_SUFFIX, ColumnType.STRING, table,
-                    table.getColumnCount(), true);
+            column = new MutableColumn(preferredColumnName + TEXT_CONTENT_TEMP_SUFFIX, ColumnType.STRING, table, table
+                    .getColumnCount(), true);
             column.setNativeType(NATIVE_TYPE_TEXT);
             table.addColumn(column);
         }
@@ -432,8 +431,8 @@
         if (column == null) {
             String tableName = table.getName();
             logger.info("Creating id column for table: " + tableName);
-            column = new MutableColumn(tableName + "_metamodel_surrogate_id", ColumnType.INTEGER, table, table.getColumnCount(),
-                    false);
+            column = new MutableColumn(tableName + "_metamodel_surrogate_id", ColumnType.INTEGER, table, table
+                    .getColumnCount(), false);
             column.setNativeType(NATIVE_TYPE_PRIMARY_KEY);
             column.setIndexed(true);
             table.addColumn(column);
@@ -543,8 +542,8 @@
         List<Object[]> tableRows = executeQuery(q).toObjectArrays();
 
         for (Column foreignColumn : foreignColumns) {
-            MutableColumn newPrimaryColumn = new MutableColumn(foreignColumn.getName(), foreignColumn.getType(), primaryTable,
-                    primaryTable.getColumnCount(), foreignColumn.isNullable());
+            MutableColumn newPrimaryColumn = new MutableColumn(foreignColumn.getName(), foreignColumn.getType(),
+                    primaryTable, primaryTable.getColumnCount(), foreignColumn.isNullable());
             newPrimaryColumn.setIndexed(foreignColumn.isIndexed());
             newPrimaryColumn.setNativeType(foreignColumn.getNativeType());
             primaryTable.addColumn(newPrimaryColumn);
@@ -558,7 +557,8 @@
         ((MutableRelationship) relationship).remove();
 
         if (logger.isInfoEnabled()) {
-            logger.info("Tables '" + primaryTableName + "' and '" + foreignTableName + "' flattened to: " + primaryTableName);
+            logger.info("Tables '" + primaryTableName + "' and '" + foreignTableName + "' flattened to: "
+                    + primaryTableName);
             if (logger.isDebugEnabled()) {
                 logger.debug(primaryTableName + " columns: " + Arrays.toString(primaryTable.getColumns()));
             }
@@ -608,7 +608,8 @@
                         Column[] foreignColumns = foreignKeyRelationship.getForeignColumns();
 
                         SelectItem countAllItem = SelectItem.getCountAllItem();
-                        Query q = new Query().select(foreignColumns).select(countAllItem).from(table).groupBy(foreignColumns);
+                        Query q = new Query().select(foreignColumns).select(countAllItem).from(table).groupBy(
+                                foreignColumns);
                         DataSet data = executeQuery(q);
                         Comparable<Object> comparable = NumberComparator.getComparable(1);
                         while (data.next()) {
diff --git a/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContext.java b/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContext.java
index fa7aa8b..f1c2d6c 100644
--- a/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContext.java
+++ b/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContext.java
@@ -23,6 +23,7 @@
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.function.Supplier;
 
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
@@ -43,7 +44,6 @@
 import org.apache.metamodel.schema.Table;
 import org.apache.metamodel.util.Action;
 import org.apache.metamodel.util.FileResource;
-import org.apache.metamodel.util.Ref;
 import org.apache.metamodel.util.Resource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -67,7 +67,7 @@
 
     public static final String COLUMN_NAME_ROW_ID = "row_id";
 
-    private final Ref<InputSource> _inputSourceRef;
+    private final Supplier<InputSource> _inputSourceRef;
     private final Map<XmlSaxTableDef, Map<String, String>> _valueXpaths;
     private String _schemaName;
     private XmlSaxTableDef[] _tableDefs;
@@ -84,7 +84,7 @@
      * 
      * @see XmlSaxTableDef
      */
-    public XmlSaxDataContext(Ref<InputSource> inputSourceRef, XmlSaxTableDef... tableDefs) {
+    public XmlSaxDataContext(Supplier<InputSource> inputSourceRef, XmlSaxTableDef... tableDefs) {
         _inputSourceRef = inputSourceRef;
         _tableDefs = tableDefs;
         _valueXpaths = new HashMap<XmlSaxTableDef, Map<String, String>>();
@@ -108,13 +108,10 @@
         this(createInputSourceRef(new FileResource(file)), tableDefs);
     }
 
-    private static Ref<InputSource> createInputSourceRef(final Resource resource) {
-        return new Ref<InputSource>() {
-            @Override
-            public InputSource get() {
-                final InputStream in = resource.read();
-                return new InputSource(in);
-            }
+    private static Supplier<InputSource> createInputSourceRef(final Resource resource) {
+        return () -> {
+            final InputStream in = resource.read();
+            return new InputSource(in);
         };
     }
 
@@ -124,8 +121,8 @@
 
         for (XmlSaxTableDef tableDef : _tableDefs) {
             final String rowXpath = tableDef.getRowXpath();
-            final MutableTable table = new MutableTable(getTableName(tableDef)).setSchema(schema).setRemarks(
-                    "XPath: " + rowXpath);
+            final MutableTable table = new MutableTable(getTableName(tableDef)).setSchema(schema).setRemarks("XPath: "
+                    + rowXpath);
 
             final MutableColumn rowIndexColumn = new MutableColumn(COLUMN_NAME_ROW_ID, ColumnType.INTEGER)
                     .setColumnNumber(0).setNullable(false).setTable(table).setRemarks("Row/tag index (0-based)");
@@ -225,8 +222,8 @@
                 SAXParserFactory saxFactory = SAXParserFactory.newInstance();
                 SAXParser saxParser = saxFactory.newSAXParser();
                 XMLReader xmlReader = saxParser.getXMLReader();
-                xmlReader
-                        .setContentHandler(new XmlSaxContentHandler(tableDef.getRowXpath(), rowPublisher, valueXpaths));
+                xmlReader.setContentHandler(new XmlSaxContentHandler(tableDef.getRowXpath(), rowPublisher,
+                        valueXpaths));
                 try {
                     xmlReader.parse(_inputSourceRef.get());
                 } catch (XmlStopParsingException e) {