METAMODEL-1165: Fixed - added default_table alias table

Closes #165

Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo
Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/fe9ab604
Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/fe9ab604
Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/fe9ab604

Branch: refs/heads/master
Commit: fe9ab604ac568fd41b55a67c0f10fe54f39d53c8
Parents: 1d56a9f
Author: Kasper Sørensen <[email protected]>
Authored: Wed Nov 1 20:57:57 2017 -0700
Committer: Kasper Sørensen <[email protected]>
Committed: Wed Nov 1 20:57:57 2017 -0700

----------------------------------------------------------------------
 CHANGES.md                                      |   1 +
 .../cassandra/CassandraDataContext.java         |   1 +
 .../apache/metamodel/AbstractDataContext.java   |  43 ++---
 .../org/apache/metamodel/MetaModelHelper.java   | 150 ++++++++--------
 .../metamodel/QueryPostprocessDataContext.java  | 175 +++++++++----------
 .../metamodel/QueryPostprocessDelegate.java     |   8 +-
 .../create/AbstractTableCreationBuilder.java    |   3 +-
 .../org/apache/metamodel/query/SelectItem.java  | 153 ++++++++--------
 .../org/apache/metamodel/schema/AliasTable.java |  82 +++++++++
 .../metamodel/schema/CompositeSchema.java       |   1 +
 .../schema/DefaultTableAliasedSchema.java       |  89 ++++++++++
 .../apache/metamodel/schema/MutableSchema.java  |  16 +-
 .../apache/metamodel/schema/WrappingSchema.java |  33 ++++
 .../apache/metamodel/schema/WrappingTable.java  |  33 ++++
 .../org/apache/metamodel/MockDataContext.java   |   1 +
 .../metamodel/MockUpdateableDataContext.java    |  16 +-
 .../QueryPostprocessDataContextTest.java        | 119 ++++++++++---
 .../intercept/InterceptableDataContextTest.java | 151 ++++++++--------
 .../apache/metamodel/query/FilterItemTest.java  |  18 +-
 .../metamodel/couchdb/CouchDbDataContext.java   |   3 +
 .../org/apache/metamodel/csv/CsvSchema.java     |   2 +-
 .../apache/metamodel/csv/CsvUpdateCallback.java |   3 +-
 .../metamodel/csv/CsvDataContextTest.java       |  25 ++-
 .../InterceptionCsvIntegrationTest.java         |   2 +-
 .../metamodel/dynamodb/DynamoDbDataContext.java |   1 +
 .../nativeclient/ElasticSearchDataContext.java  |   1 +
 .../rest/ElasticSearchRestDataContext.java      |   1 +
 .../metamodel/excel/ExcelDataContext.java       |   2 +
 .../excel/ExcelTableCreationBuilder.java        |   2 +-
 .../metamodel/excel/ExcelDataContextTest.java   |  22 +--
 .../excel/ExcelUpdateCallbackTest.java          |   2 +-
 .../fixedwidth/FixedWidthDataContext.java       |   2 +
 .../fixedwidth/FixedWidthDataContextTest.java   |  10 +-
 .../metamodel/hbase/HBaseDataContext.java       |   2 +
 .../apache/metamodel/json/JsonDataContext.java  |   1 +
 .../mongodb/mongo2/MongoDbDataContext.java      |   1 +
 .../mongodb/mongo3/MongoDbDataContext.java      |   1 +
 .../metamodel/neo4j/Neo4jDataContext.java       |   8 +
 .../apache/metamodel/pojo/PojoDataContext.java  |   1 +
 .../metamodel/pojo/PojoDataContextTest.java     |   4 +-
 .../salesforce/SalesforceDataContext.java       |   4 +
 .../metamodel/sugarcrm/SugarCrmDataContext.java |   1 +
 .../apache/metamodel/xml/XmlDomDataContext.java |   3 +
 .../apache/metamodel/xml/XmlSaxDataContext.java |   1 +
 .../metamodel/xml/XmlDomDataContextTest.java    |   3 +-
 45 files changed, 765 insertions(+), 436 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index b2ea491..ddd3c9a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -9,6 +9,7 @@
  * [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.
+ * [METAMODEL-1165] - Added a convenient alias table "default_table" for 
single-table data stores.
  * [METAMODEL-1144] - Optimized evaluation of conditional client-side JOIN 
statements.
  * [METAMODEL-1145] - Fixed bug with modelling JDBC table relationships when 
there are multiple keys involved in the relationship.
  * [METAMODEL-1151] - Added DataContextFactory classes for instantiating 
DataContexts of many types based on properties.

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/cassandra/src/main/java/org/apache/metamodel/cassandra/CassandraDataContext.java
----------------------------------------------------------------------
diff --git 
a/cassandra/src/main/java/org/apache/metamodel/cassandra/CassandraDataContext.java
 
b/cassandra/src/main/java/org/apache/metamodel/cassandra/CassandraDataContext.java
index 08d3fd9..88c4b67 100644
--- 
a/cassandra/src/main/java/org/apache/metamodel/cassandra/CassandraDataContext.java
+++ 
b/cassandra/src/main/java/org/apache/metamodel/cassandra/CassandraDataContext.java
@@ -87,6 +87,7 @@ public class CassandraDataContext extends 
QueryPostprocessDataContext implements
      *            and column model of the ElasticSearch index.
      */
     public CassandraDataContext(Cluster cluster, String keySpace, 
SimpleTableDef... tableDefs) {
+        super(false);
         this.cassandraCluster = cluster;
         this.keySpaceName = keySpace;
         this.tableDefs = tableDefs;

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/AbstractDataContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/AbstractDataContext.java 
b/core/src/main/java/org/apache/metamodel/AbstractDataContext.java
index 475add4..c098167 100644
--- a/core/src/main/java/org/apache/metamodel/AbstractDataContext.java
+++ b/core/src/main/java/org/apache/metamodel/AbstractDataContext.java
@@ -34,10 +34,11 @@ import org.apache.metamodel.query.parser.QueryParser;
 import org.apache.metamodel.schema.Column;
 import org.apache.metamodel.schema.Schema;
 import org.apache.metamodel.schema.Table;
+import org.apache.metamodel.schema.TableType;
 
 /**
- * Abstract implementation of the DataContext interface. Provides convenient
- * implementations of all trivial and datastore-independent methods.
+ * Abstract implementation of the DataContext interface. Provides convenient 
implementations of all trivial and
+ * datastore-independent methods.
  */
 public abstract class AbstractDataContext implements DataContext {
 
@@ -58,9 +59,8 @@ public abstract class AbstractDataContext implements 
DataContext {
     }
 
     /**
-     * Method invoked when schemas have been refreshed using
-     * {@link #refreshSchemas()}. Can be overridden to add callback
-     * functionality in subclasses.
+     * Method invoked when schemas have been refreshed using {@link 
#refreshSchemas()}. Can be overridden to add
+     * callback functionality in subclasses.
      */
     protected void onSchemaCacheRefreshed() {
     }
@@ -72,7 +72,7 @@ public abstract class AbstractDataContext implements 
DataContext {
     public final List<Schema> getSchemas() throws MetaModelException {
         List<String> schemaNames = getSchemaNames();
         List<Schema> schemas = new ArrayList<>();
-        for (final String name: schemaNames) {
+        for (final String name : schemaNames) {
             final Schema schema = _schemaCache.get(getSchemaCacheKey(name));
             if (schema == null) {
                 final Schema newSchema = getSchemaByName(name);
@@ -128,7 +128,7 @@ public abstract class AbstractDataContext implements 
DataContext {
                 result = schemas.get(0);
             } else {
                 int highestTableCount = -1;
-                for (Schema schema: schemas) {
+                for (Schema schema : schemas) {
                     String name = schema.getName();
                     if (schema != null) {
                         name = name.toLowerCase();
@@ -299,13 +299,10 @@ public abstract class AbstractDataContext implements 
DataContext {
     /**
      * Searches for a particular column within a schema
      * 
-     * @param schemaNameSearch
-     *            the schema name to use for search
-     * @param columnNameOriginal
-     *            the original column name
-     * @param columnNameSearch
-     *            the column name as it should be searched for (either the same
-     *            as original, or lower case in case of case-insensitive 
search)
+     * @param schemaNameSearch the schema name to use for search
+     * @param columnNameOriginal the original column name
+     * @param columnNameSearch the column name as it should be searched for 
(either the same as original, or lower case
+     *            in case of case-insensitive search)
      * @return
      */
     private Column searchColumn(String schemaNameSearch, String 
columnNameOriginal, String columnNameSearch) {
@@ -365,7 +362,7 @@ public abstract class AbstractDataContext implements 
DataContext {
             }
         }
 
-        if (table == null && tableNames.size() == 1) {
+        if (table == null && schema.getTables().stream().filter(t -> 
t.getType() != TableType.ALIAS).count() == 1) {
             table = schema.getTables().get(0);
         }
 
@@ -536,9 +533,8 @@ public abstract class AbstractDataContext implements 
DataContext {
     }
 
     /**
-     * Gets schema names from the non-abstract implementation. These schema
-     * names will be cached except if the {@link #refreshSchemas()} method is
-     * called.
+     * Gets schema names from the non-abstract implementation. These schema 
names will be cached except if the
+     * {@link #refreshSchemas()} method is called.
      * 
      * @return an array of schema names.
      */
@@ -552,14 +548,11 @@ public abstract class AbstractDataContext implements 
DataContext {
     protected abstract String getDefaultSchemaName();
 
     /**
-     * Gets a specific schema from the non-abstract implementation. This schema
-     * object will be cached except if the {@link #refreshSchemas()} method is
-     * called.
+     * Gets a specific schema from the non-abstract implementation. This 
schema object will be cached except if the
+     * {@link #refreshSchemas()} method is called.
      * 
-     * @param name
-     *            the name of the schema to get
-     * @return a schema object representing the named schema, or null if no 
such
-     *         schema exists.
+     * @param name the name of the schema to get
+     * @return a schema object representing the named schema, or null if no 
such schema exists.
      */
     protected abstract Schema getSchemaByNameInternal(String name);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/MetaModelHelper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/MetaModelHelper.java 
b/core/src/main/java/org/apache/metamodel/MetaModelHelper.java
index 4c705ff..2b547da 100644
--- a/core/src/main/java/org/apache/metamodel/MetaModelHelper.java
+++ b/core/src/main/java/org/apache/metamodel/MetaModelHelper.java
@@ -18,12 +18,21 @@
  */
 package org.apache.metamodel;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-
 import org.apache.metamodel.data.CachingDataSetHeader;
 import org.apache.metamodel.data.DataSet;
 import org.apache.metamodel.data.DataSetHeader;
@@ -51,6 +60,8 @@ import org.apache.metamodel.schema.ColumnType;
 import org.apache.metamodel.schema.Schema;
 import org.apache.metamodel.schema.SuperColumnType;
 import org.apache.metamodel.schema.Table;
+import org.apache.metamodel.schema.WrappingSchema;
+import org.apache.metamodel.schema.WrappingTable;
 import org.apache.metamodel.util.AggregateBuilder;
 import org.apache.metamodel.util.CollectionUtils;
 import org.apache.metamodel.util.ObjectComparator;
@@ -58,18 +69,17 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * This class contains various helper functionality to common tasks in
- * MetaModel, eg.:
+ * This class contains various helper functionality to common tasks in 
MetaModel, eg.:
  * 
  * <ul>
  * <li>Easy-access for traversing common schema items</li>
- * <li>Manipulate data in memory. These methods are primarily used to enable
- * queries for non-queryable data sources like CSV files and spreadsheets.</li>
+ * <li>Manipulate data in memory. These methods are primarily used to enable 
queries for non-queryable data sources like
+ * CSV files and spreadsheets.</li>
  * <li>Query rewriting, traversing and manipulation.</li>
  * </ul>
  * 
- * The class is mainly intended for internal use within the framework
- * operations, but is kept stable, so it can also be used by framework users.
+ * The class is mainly intended for internal use within the framework 
operations, but is kept stable, so it can also be
+ * used by framework users.
  */
 public final class MetaModelHelper {
 
@@ -80,8 +90,7 @@ public final class MetaModelHelper {
     }
 
     /**
-     * Creates an array of tables where all occurences of tables in the 
provided
-     * list of tables and columns are included
+     * Creates an array of tables where all occurences of tables in the 
provided list of tables and columns are included
      */
     public static Table[] getTables(Collection<Table> tableList, 
Iterable<Column> columnList) {
         HashSet<Table> set = new HashSet<Table>();
@@ -119,8 +128,7 @@ public final class MetaModelHelper {
     /**
      * Converts a list of columns to a corresponding array of tables
      * 
-     * @param columns
-     *            the columns that the tables will be extracted from
+     * @param columns the columns that the tables will be extracted from
      * @return an array containing the tables of the provided columns.
      */
     public static Table[] getTables(Iterable<Column> columns) {
@@ -135,8 +143,7 @@ public final class MetaModelHelper {
     }
 
     /**
-     * Creates a subset array of columns, where only columns that are contained
-     * within the specified table are included.
+     * Creates a subset array of columns, where only columns that are 
contained within the specified table are included.
      * 
      * @param table
      * @param columns
@@ -157,8 +164,7 @@ public final class MetaModelHelper {
     }
 
     /**
-     * Creates a subset array of columns, where only columns that are contained
-     * within the specified table are included.
+     * Creates a subset array of columns, where only columns that are 
contained within the specified table are included.
      * 
      * @param table
      * @param columns
@@ -185,7 +191,6 @@ public final class MetaModelHelper {
         // do a nested loop join, no matter what
         Iterator<DataSet> dsIter = Arrays.asList(fromDataSets).iterator();
 
-
         DataSet joined = dsIter.next();
 
         while (dsIter.hasNext()) {
@@ -198,8 +203,7 @@ public final class MetaModelHelper {
     }
 
     /**
-     * Executes a simple nested loop join. The innerLoopDs will be copied in an
-     * in-memory dataset.
+     * Executes a simple nested loop join. The innerLoopDs will be copied in 
an in-memory dataset.
      *
      */
     public static InMemoryDataSet nestedLoopJoin(DataSet innerLoopDs, DataSet 
outerLoopDs,
@@ -225,8 +229,8 @@ public final class MetaModelHelper {
                 Object[] joinedRowObjects = new 
Object[outerRow.getValues().length + innerRow.getValues().length];
 
                 System.arraycopy(outerRow.getValues(), 0, joinedRowObjects, 0, 
outerRow.getValues().length);
-                System.arraycopy(innerRow.getValues(), 0, joinedRowObjects, 
outerRow.getValues().length, innerRow
-                        .getValues().length);
+                System.arraycopy(innerRow.getValues(), 0, joinedRowObjects, 
outerRow.getValues().length,
+                        innerRow.getValues().length);
 
                 Row joinedRow = new DefaultRow(jointHeader, joinedRowObjects);
 
@@ -240,8 +244,8 @@ public final class MetaModelHelper {
     }
 
     /**
-     * Filters the FilterItems such that only the FilterItems are returned,
-     * which contain SelectItems that are contained in selectItemList
+     * Filters the FilterItems such that only the FilterItems are returned, 
which contain SelectItems that are contained
+     * in selectItemList
      * 
      * @param filters
      * @param selectItemList
@@ -293,8 +297,8 @@ public final class MetaModelHelper {
 
         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);
                 }
             }
@@ -304,8 +308,8 @@ public final class MetaModelHelper {
             return new SubSelectionDataSet(selectItems, dataSet);
         }
 
-        final ScalarFunctionDataSet scalaFunctionDataSet = new 
ScalarFunctionDataSet(
-                scalarFunctionSelectItemsToEvaluate, dataSet);
+        final ScalarFunctionDataSet scalaFunctionDataSet =
+                new ScalarFunctionDataSet(scalarFunctionSelectItemsToEvaluate, 
dataSet);
         return new SubSelectionDataSet(selectItems, scalaFunctionDataSet);
     }
 
@@ -318,9 +322,8 @@ public final class MetaModelHelper {
         if (groupByItems != null && groupByItems.size() > 0) {
             Map<Row, Map<SelectItem, List<Object>>> uniqueRows = new 
HashMap<Row, Map<SelectItem, List<Object>>>();
 
-            final List<SelectItem> groupBySelects = groupByItems.stream()
-                    .map(gbi -> gbi.getSelectItem())
-                    .collect(Collectors.toList());
+            final List<SelectItem> groupBySelects =
+                    groupByItems.stream().map(gbi -> 
gbi.getSelectItem()).collect(Collectors.toList());
             final DataSetHeader groupByHeader = new 
CachingDataSetHeader(groupBySelects);
 
             // Creates a list of SelectItems that have aggregate functions
@@ -413,13 +416,10 @@ public final class MetaModelHelper {
     }
 
     /**
-     * Applies aggregate values to a dataset. This method is to be invoked 
AFTER
-     * any filters have been applied.
+     * Applies aggregate values to a dataset. This method is to be invoked 
AFTER any filters have been applied.
      * 
-     * @param workSelectItems
-     *            all select items included in the processing of the query
-     *            (including those originating from other clauses than the
-     *            SELECT clause).
+     * @param workSelectItems all select items included in the processing of 
the query (including those originating from
+     *            other clauses than the SELECT clause).
      * @param dataSet
      * @return
      */
@@ -595,12 +595,10 @@ public final class MetaModelHelper {
     }
 
     /**
-     * Examines a query and extracts an array of FromItem's that refer
-     * (directly) to tables (hence Joined FromItems and SubQuery FromItems are
-     * traversed but not included).
+     * Examines a query and extracts an array of FromItem's that refer 
(directly) to tables (hence Joined FromItems and
+     * SubQuery FromItems are traversed but not included).
      * 
-     * @param q
-     *            the query to examine
+     * @param q the query to examine
      * @return an array of FromItem's that refer directly to tables
      */
     public static FromItem[] getTableFromItems(Query q) {
@@ -633,16 +631,12 @@ public final class MetaModelHelper {
     }
 
     /**
-     * Executes a single row query, like "SELECT COUNT(*), MAX(SOME_COLUMN) 
FROM
-     * MY_TABLE" or similar.
+     * Executes a single row query, like "SELECT COUNT(*), MAX(SOME_COLUMN) 
FROM MY_TABLE" or similar.
      * 
-     * @param dataContext
-     *            the DataContext object to use for executing the query
-     * @param query
-     *            the query to execute
+     * @param dataContext the DataContext object to use for executing the query
+     * @param query the query to execute
      * @return a row object representing the single row returned from the query
-     * @throws MetaModelException
-     *             if less or more than one Row is returned from the query
+     * @throws MetaModelException if less or more than one Row is returned 
from the query
      */
     public static Row executeSingleRowQuery(DataContext dataContext, Query 
query) throws MetaModelException {
         DataSet dataSet = dataContext.executeQuery(query);
@@ -662,12 +656,9 @@ public final class MetaModelHelper {
     /**
      * Performs a left join (aka left outer join) operation on two datasets.
      * 
-     * @param ds1
-     *            the left dataset
-     * @param ds2
-     *            the right dataset
-     * @param onConditions
-     *            the conditions to join by
+     * @param ds1 the left dataset
+     * @param ds2 the right dataset
+     * @param onConditions the conditions to join by
      * @return the left joined result dataset
      */
     public static DataSet getLeftJoin(DataSet ds1, DataSet ds2, FilterItem[] 
onConditions) {
@@ -679,7 +670,7 @@ public final class MetaModelHelper {
         }
         List<SelectItem> si1 = ds1.getSelectItems();
         List<SelectItem> si2 = ds2.getSelectItems();
-        List<SelectItem> selectItems = 
Stream.concat(si1.stream(),si2.stream()).collect(Collectors.toList());
+        List<SelectItem> selectItems = Stream.concat(si1.stream(), 
si2.stream()).collect(Collectors.toList());
         List<Row> resultRows = new ArrayList<Row>();
         List<Row> ds2data = readDataSetFull(ds2);
         if (ds2data.isEmpty()) {
@@ -698,9 +689,9 @@ public final class MetaModelHelper {
             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);
@@ -723,12 +714,9 @@ public final class MetaModelHelper {
     /**
      * Performs a right join (aka right outer join) operation on two datasets.
      * 
-     * @param ds1
-     *            the left dataset
-     * @param ds2
-     *            the right dataset
-     * @param onConditions
-     *            the conditions to join by
+     * @param ds1 the left dataset
+     * @param ds2 the right dataset
+     * @param onConditions the conditions to join by
      * @return the right joined result dataset
      */
     public static DataSet getRightJoin(DataSet ds1, DataSet ds2, FilterItem[] 
onConditions) {
@@ -756,9 +744,7 @@ public final class MetaModelHelper {
 
     public static DataSet getDistinct(DataSet dataSet) {
         List<SelectItem> selectItems = dataSet.getSelectItems();
-        List<GroupByItem> groupByItems = selectItems.stream()
-                .map(GroupByItem::new)
-                .collect(Collectors.toList());
+        List<GroupByItem> groupByItems = 
selectItems.stream().map(GroupByItem::new).collect(Collectors.toList());
 
         return getGrouped(selectItems, dataSet, groupByItems);
     }
@@ -836,11 +822,10 @@ public final class MetaModelHelper {
     }
 
     /**
-     * Determines if a query contains {@link ScalarFunction}s in any clause of
-     * the query EXCEPT for the SELECT clause. This is a handy thing to
-     * determine because decorating with {@link ScalarFunctionDataSet} only
-     * gives you select-item evaluation so if the rest of the query is pushed 
to
-     * an underlying datastore, then it may create issues.
+     * Determines if a query contains {@link ScalarFunction}s in any clause of 
the query EXCEPT for the SELECT clause.
+     * This is a handy thing to determine because decorating with {@link 
ScalarFunctionDataSet} only gives you
+     * select-item evaluation so if the rest of the query is pushed to an 
underlying datastore, then it may create
+     * issues.
      * 
      * @param query
      * @return
@@ -883,4 +868,23 @@ public final class MetaModelHelper {
 
         return false;
     }
+
+    public static Table resolveTable(FromItem fromItem) {
+        final Table table = fromItem.getTable();
+        return resolveUnderlyingTable(table);
+    }
+
+    public static Table resolveUnderlyingTable(Table table) {
+        while (table instanceof WrappingTable) {
+            table = ((WrappingTable) table).getWrappedTable();
+        }
+        return table;
+    }
+
+    public static Schema resolveUnderlyingSchema(Schema schema) {
+        while (schema instanceof WrappingSchema) {
+            schema = ((WrappingSchema) schema).getWrappedSchema();
+        }
+        return schema;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java 
b/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java
index cbd97d3..c77479b 100644
--- a/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java
+++ b/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java
@@ -50,6 +50,7 @@ import org.apache.metamodel.query.SelectClause;
 import org.apache.metamodel.query.SelectItem;
 import org.apache.metamodel.schema.Column;
 import org.apache.metamodel.schema.ColumnType;
+import org.apache.metamodel.schema.DefaultTableAliasedSchema;
 import org.apache.metamodel.schema.MutableColumn;
 import org.apache.metamodel.schema.MutableRelationship;
 import org.apache.metamodel.schema.MutableSchema;
@@ -63,24 +64,37 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Abstract DataContext for data sources that do not support SQL queries
- * natively.
+ * Abstract DataContext for data sources that do not support SQL queries 
natively.
  * 
- * Instead this superclass only requires that a subclass can materialize a
- * single table at a time. Then the query will be executed by post processing
- * the datasets client-side.
+ * Instead this superclass only requires that a subclass can materialize a 
single table at a time. Then the query will
+ * be executed by post processing the datasets client-side.
  */
 public abstract class QueryPostprocessDataContext extends AbstractDataContext 
implements HasReadTypeConverters {
 
     private static final Logger logger = 
LoggerFactory.getLogger(QueryPostprocessDataContext.class);
 
+    public static final String SYSTEM_PROPERTY_CREATE_DEFAULT_TABLE_ALIAS = 
"metamodel.alias.default.table";
     public static final String INFORMATION_SCHEMA_NAME = "information_schema";
 
-    private final Map<Column, TypeConverter<?, ?>> _converters;
+    private final Map<Column, TypeConverter<?, ?>> converters;
+    private final boolean singleTableDatastore;
 
     public QueryPostprocessDataContext() {
+        this(true);
+    }
+
+    /**
+     * 
+     * @param singleTableDatastore a flag that, if set to true, indicates that 
this DataContext contains just a single
+     *            table. This information will be used to optimize and provide 
convenience for the implementation. An
+     *            additional {@link Table} of type {@link TableType#ALIAS} 
with the name "default_table" will be
+     *            automatically added in addition to the single table. That 
again makes for convenient querying of the
+     *            single table using a predictable name/alias.
+     */
+    public QueryPostprocessDataContext(boolean singleTableDatastore) {
         super();
-        _converters = new HashMap<Column, TypeConverter<?, ?>>();
+        this.singleTableDatastore = singleTableDatastore;
+        this.converters = new HashMap<Column, TypeConverter<?, ?>>();
     }
 
     @Override
@@ -112,7 +126,7 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
         if (singleFromItem && noGrouping) {
 
             final FromItem fromItem = query.getFromClause().getItem(0);
-            final Table table = fromItem.getTable();
+            final Table table = MetaModelHelper.resolveTable(fromItem);
             if (table != null) {
 
                 // check for SELECT COUNT(*) queries
@@ -128,7 +142,7 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
                                 logger.debug(
                                         "DataContext did not return any count 
query results. Proceeding with manual counting.");
                             } else {
-                                List<Row> data = new ArrayList<Row>(1);
+                                final List<Row> data = new ArrayList<Row>(1);
                                 final DataSetHeader header = new 
SimpleDataSetHeader(new SelectItem[] { selectItem });
                                 data.add(new DefaultRow(header, new Object[] { 
count }));
                                 return new InMemoryDataSet(header, data);
@@ -151,8 +165,8 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
                                 if (table != null) {
                                     if (isMainSchemaTable(table)) {
                                         final Object operand = 
whereItem.getOperand();
-                                        final Row row = 
executePrimaryKeyLookupQuery(table, selectItems, column,
-                                                operand);
+                                        final Row row =
+                                                
executePrimaryKeyLookupQuery(table, selectItems, column, operand);
                                         if (row == null) {
                                             logger.debug(
                                                     "DataContext did not 
return any GET query results. Proceeding with manual lookup.");
@@ -192,8 +206,8 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
 
         // we can now exclude the select items imposed by the WHERE clause (and
         // should, to make the aggregation process faster)
-        workSelectItems = CollectionUtils.concat(true, selectItems, 
groupBySelectItems, havingSelectItems,
-                orderBySelectItems);
+        workSelectItems =
+                CollectionUtils.concat(true, selectItems, groupBySelectItems, 
havingSelectItems, orderBySelectItems);
 
         if (groupByItems.size() > 0) {
             dataSet = MetaModelHelper.getGrouped(workSelectItems, dataSet, 
groupByItems);
@@ -216,8 +230,7 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
     }
 
     /**
-     * Determines if all the select items are 'simple' meaning that they just
-     * represent scans of values in columns.
+     * Determines if all the select items are 'simple' meaning that they just 
represent scans of values in columns.
      *
      * @param clause
      * @return
@@ -235,17 +248,13 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
     }
 
     /**
-     * Executes a simple count query, if possible. This method is provided to
-     * allow subclasses to optimize count queries since they are quite common
-     * and often a datastore can retrieve the count using some specialized 
means
-     * which is much more performant than counting all records manually.
+     * Executes a simple count query, if possible. This method is provided to 
allow subclasses to optimize count queries
+     * since they are quite common and often a datastore can retrieve the 
count using some specialized means which is
+     * much more performant than counting all records manually.
      * 
-     * @param table
-     *            the table on which the count is requested.
-     * @param whereItems
-     *            a (sometimes empty) list of WHERE items.
-     * @param functionApproximationAllowed
-     *            whether approximation is allowed or not.
+     * @param table the table on which the count is requested.
+     * @param whereItems a (sometimes empty) list of WHERE items.
+     * @param functionApproximationAllowed whether approximation is allowed or 
not.
      * @return the count of the particular table, or null if not available.
      */
     protected Number executeCountQuery(Table table, List<FilterItem> 
whereItems, boolean functionApproximationAllowed) {
@@ -253,20 +262,14 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
     }
 
     /**
-     * Executes a query which obtains a row by primary key (as defined by
-     * {@link Column#isPrimaryKey()}). This method is provided to allow
-     * subclasses to optimize lookup queries since they are quite common and
-     * often a datastore can retrieve the row using some specialized means 
which
-     * is much more performant than scanning all records manually.
+     * Executes a query which obtains a row by primary key (as defined by 
{@link Column#isPrimaryKey()}). This method is
+     * provided to allow subclasses to optimize lookup queries since they are 
quite common and often a datastore can
+     * retrieve the row using some specialized means which is much more 
performant than scanning all records manually.
      * 
-     * @param table
-     *            the table on which the lookup is requested.
-     * @param selectItems
-     *            the items to select from the lookup query.
-     * @param primaryKeyColumn
-     *            the column that is the primary key
-     * @param keyValue
-     *            the primary key value that is specified in the lookup query.
+     * @param table the table on which the lookup is requested.
+     * @param selectItems the items to select from the lookup query.
+     * @param primaryKeyColumn the column that is the primary key
+     * @param keyValue the primary key value that is specified in the lookup 
query.
      * @return the row if the particular table, or null if not available.
      */
     protected Row executePrimaryKeyLookupQuery(Table table, List<SelectItem> 
selectItems, Column primaryKeyColumn,
@@ -279,7 +282,7 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
         JoinType joinType = fromItem.getJoin();
         if (fromItem.getTable() != null) {
             // We need to materialize a single table
-            final Table table = fromItem.getTable();
+            final Table table = MetaModelHelper.resolveTable(fromItem);
             final List<SelectItem> selectItemsToMaterialize = new 
ArrayList<SelectItem>();
 
             for (final SelectItem selectItem : selectItems) {
@@ -319,13 +322,13 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
 
             // materialize left side
             final List<SelectItem> leftOn = 
Arrays.asList(fromItem.getLeftOn());
-            fromItemDataSets[0] = materializeFromItem(fromItem.getLeftSide(),
-                    CollectionUtils.concat(true, selectItems, leftOn));
+            fromItemDataSets[0] =
+                    materializeFromItem(fromItem.getLeftSide(), 
CollectionUtils.concat(true, selectItems, leftOn));
 
             // materialize right side
             final List<SelectItem> rightOn = 
Arrays.asList(fromItem.getRightOn());
-            fromItemDataSets[1] = materializeFromItem(fromItem.getRightSide(),
-                    CollectionUtils.concat(true, selectItems, rightOn));
+            fromItemDataSets[1] =
+                    materializeFromItem(fromItem.getRightSide(), 
CollectionUtils.concat(true, selectItems, rightOn));
 
             final FilterItem[] onConditions = new FilterItem[leftOn.size()];
             for (int i = 0; i < onConditions.length; i++) {
@@ -385,8 +388,8 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
 
         final DataSet dataSet;
         if (INFORMATION_SCHEMA_NAME.equals(schemaName)) {
-            DataSet informationDataSet = 
materializeInformationSchemaTable(table,
-                    buildWorkingSelectItems(selectItems, whereItems));
+            DataSet informationDataSet =
+                    materializeInformationSchemaTable(table, 
buildWorkingSelectItems(selectItems, whereItems));
             informationDataSet = 
MetaModelHelper.getFiltered(informationDataSet, whereItems);
             informationDataSet = MetaModelHelper.getSelection(selectItems, 
informationDataSet);
             informationDataSet = MetaModelHelper.getPaged(informationDataSet, 
firstRow, maxRows);
@@ -396,7 +399,7 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
 
             // conversion is done at materialization time, since it enables
             // the refined types to be used also in eg. where clauses.
-            dataSet = new 
ConvertedDataSetInterceptor(_converters).intercept(tableDataSet);
+            dataSet = new 
ConvertedDataSetInterceptor(converters).intercept(tableDataSet);
         }
 
         return dataSet;
@@ -418,13 +421,11 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
     }
 
     /**
-     * Determines if the subclass of this class can materialize
-     * {@link SelectItem}s with the given {@link ScalarFunction}. Usually 
scalar
-     * functions are applied by MetaModel on the client side, but when possible
-     * they can also be handled by e.g.
-     * {@link #materializeMainSchemaTable(Table, List, int, int)} and
-     * {@link #materializeMainSchemaTable(Table, List, List, int, int)} in 
which
-     * case MetaModel will not evaluate it client-side.
+     * Determines if the subclass of this class can materialize {@link 
SelectItem}s with the given
+     * {@link ScalarFunction}. Usually scalar functions are applied by 
MetaModel on the client side, but when possible
+     * they can also be handled by e.g. {@link 
#materializeMainSchemaTable(Table, List, int, int)} and
+     * {@link #materializeMainSchemaTable(Table, List, List, int, int)} in 
which case MetaModel will not evaluate it
+     * client-side.
      * 
      * @param function
      * @return
@@ -458,15 +459,18 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
     @Override
     protected final Schema getSchemaByNameInternal(final String name) throws 
MetaModelException {
         final String mainSchemaName = getMainSchemaName();
-        if (name == null) {
-            if (mainSchemaName == null) {
-                return getMainSchema();
-            }
+        if (name == null && mainSchemaName != null) {
             return null;
         }
 
-        if (name.equalsIgnoreCase(mainSchemaName)) {
-            return getMainSchema();
+        if (name == null || name.equalsIgnoreCase(mainSchemaName)) {
+            final Schema mainSchema = getMainSchema();
+            final boolean createAliasTable = singleTableDatastore
+                    && 
Boolean.parseBoolean(System.getProperty(SYSTEM_PROPERTY_CREATE_DEFAULT_TABLE_ALIAS,
 "true"));
+            if (createAliasTable) {
+                return DefaultTableAliasedSchema.wrapIfAppropriate(mainSchema);
+            }
+            return mainSchema;
         } else if (name.equals(INFORMATION_SCHEMA_NAME)) {
             return getInformationSchema();
         }
@@ -528,9 +532,8 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
 
     private DataSet materializeInformationSchemaTable(final Table table, final 
List<SelectItem> selectItems) {
         final String tableName = table.getName();
-        final List<SelectItem> columnSelectItems = table.getColumns().stream()
-                .map(SelectItem::new)
-                .collect(Collectors.toList());
+        final List<SelectItem> columnSelectItems =
+                
table.getColumns().stream().map(SelectItem::new).collect(Collectors.toList());
         final SimpleDataSetHeader header = new 
SimpleDataSetHeader(columnSelectItems);
         final List<Table> tables = getDefaultSchema().getTables();
         final List<Row> data = new ArrayList<Row>();
@@ -591,15 +594,14 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
     }
 
     /**
-     * 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
-     * {@link Converters#addTypeConverter(DataContext, Column, TypeConverter)}
-     * to ensure conversion on both reads and writes.
+     * 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
+     * {@link Converters#addTypeConverter(DataContext, Column, TypeConverter)} 
to ensure conversion on both reads and
+     * writes.
      */
     @Override
     public void addConverter(Column column, TypeConverter<?, ?> converter) {
-        _converters.put(column, converter);
+        converters.put(column, converter);
     }
 
     /**
@@ -613,10 +615,9 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
     protected abstract String getMainSchemaName() throws MetaModelException;
 
     /**
-     * Execute a simple one-table query against a table in the main schema of
-     * the subclasses of this class. This default implementation will delegate
-     * to {@link #materializeMainSchemaTable(Table, List, int, int)} and apply
-     * WHERE item filtering afterwards.
+     * Execute a simple one-table query against a table in the main schema of 
the subclasses of this class. This default
+     * implementation will delegate to {@link 
#materializeMainSchemaTable(Table, List, int, int)} and apply WHERE item
+     * filtering afterwards.
      * 
      * @param table
      * @param selectItems
@@ -644,9 +645,8 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
     }
 
     /**
-     * Executes a simple one-table query against a table in the main schema of
-     * the subclasses of this class. This default implementation will delegate
-     * to {@link #materializeMainSchemaTable(Table, List, int, int)}.
+     * Executes a simple one-table query against a table in the main schema of 
the subclasses of this class. This
+     * default implementation will delegate to {@link 
#materializeMainSchemaTable(Table, List, int, int)}.
      *
      * @param table
      * @param selectItems
@@ -654,10 +654,9 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
      * @param maxRows
      * @return
      */
-    protected DataSet materializeMainSchemaTableSelect(Table table, 
List<SelectItem> selectItems, int firstRow, int maxRows) {
-        List<Column> columns = selectItems.stream()
-                .map(si -> si.getColumn())
-                .collect(Collectors.toList());
+    protected DataSet materializeMainSchemaTableSelect(Table table, 
List<SelectItem> selectItems, int firstRow,
+            int maxRows) {
+        List<Column> columns = selectItems.stream().map(si -> 
si.getColumn()).collect(Collectors.toList());
 
         DataSet dataSet = materializeMainSchemaTable(table, columns, firstRow, 
maxRows);
 
@@ -667,9 +666,8 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
     }
 
     /**
-     * Executes a simple one-table query against a table in the main schema of
-     * the subclasses of this class. This default implementation will delegate
-     * to {@link #materializeMainSchemaTable(Table, List, int)} and apply a
+     * Executes a simple one-table query against a table in the main schema of 
the subclasses of this class. This
+     * default implementation will delegate to {@link 
#materializeMainSchemaTable(Table, List, int)} and apply a
      * {@link FirstRowDataSet} if necessary.
      * 
      * @param table
@@ -693,16 +691,11 @@ public abstract class QueryPostprocessDataContext extends 
AbstractDataContext im
     }
 
     /**
-     * Executes a simple one-table query against a table in the main schema of
-     * the subclasses of this class.
+     * Executes a simple one-table query against a table in the main schema of 
the subclasses of this class.
      * 
-     * @param table
-     *            the table to query
-     * @param columns
-     *            the columns of the table to query
-     * @param maxRows
-     *            the maximum amount of rows needed or -1 if all rows are
-     *            wanted.
+     * @param table the table to query
+     * @param columns the columns of the table to query
+     * @param maxRows the maximum amount of rows needed or -1 if all rows are 
wanted.
      * @return a dataset with the raw table/column content.
      */
     protected abstract DataSet materializeMainSchemaTable(Table table, 
List<Column> columns, int maxRows);

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/QueryPostprocessDelegate.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/QueryPostprocessDelegate.java 
b/core/src/main/java/org/apache/metamodel/QueryPostprocessDelegate.java
index 9e0e4dc..1c94ff9 100644
--- a/core/src/main/java/org/apache/metamodel/QueryPostprocessDelegate.java
+++ b/core/src/main/java/org/apache/metamodel/QueryPostprocessDelegate.java
@@ -18,7 +18,7 @@
  */
 package org.apache.metamodel;
 
-import org.apache.metamodel.schema.Schema;
+import org.apache.metamodel.schema.MutableSchema;
 
 /**
  * A simple subclass of {@link QueryPostprocessDataContext} which provides less
@@ -27,6 +27,10 @@ import org.apache.metamodel.schema.Schema;
  */
 public abstract class QueryPostprocessDelegate extends
                QueryPostprocessDataContext {
+    
+    public QueryPostprocessDelegate() {
+        super(false);
+    }
 
        @Override
        protected String getMainSchemaName() throws MetaModelException {
@@ -35,7 +39,7 @@ public abstract class QueryPostprocessDelegate extends
        }
 
        @Override
-       protected Schema getMainSchema() throws MetaModelException {
+       protected MutableSchema getMainSchema() throws MetaModelException {
                throw new UnsupportedOperationException(
                                "QueryPostprocessDelegate cannot perform schema 
exploration");
        }

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/create/AbstractTableCreationBuilder.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/create/AbstractTableCreationBuilder.java
 
b/core/src/main/java/org/apache/metamodel/create/AbstractTableCreationBuilder.java
index 1833120..7ca7216 100644
--- 
a/core/src/main/java/org/apache/metamodel/create/AbstractTableCreationBuilder.java
+++ 
b/core/src/main/java/org/apache/metamodel/create/AbstractTableCreationBuilder.java
@@ -18,6 +18,7 @@
  */
 package org.apache.metamodel.create;
 
+import org.apache.metamodel.MetaModelHelper;
 import org.apache.metamodel.UpdateCallback;
 import org.apache.metamodel.schema.Column;
 import org.apache.metamodel.schema.ColumnType;
@@ -50,7 +51,7 @@ public abstract class AbstractTableCreationBuilder<U extends 
UpdateCallback> imp
                     + schema);
         }
         _updateCallback = updateCallback;
-        _schema = schema;
+        _schema = MetaModelHelper.resolveUnderlyingSchema(schema);
         _table = new MutableTable(name, TableType.TABLE, schema);
     }
 

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/query/SelectItem.java
----------------------------------------------------------------------
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 df4b995..fec900d 100644
--- a/core/src/main/java/org/apache/metamodel/query/SelectItem.java
+++ b/core/src/main/java/org/apache/metamodel/query/SelectItem.java
@@ -25,6 +25,7 @@ import org.apache.metamodel.schema.Column;
 import org.apache.metamodel.schema.ColumnType;
 import org.apache.metamodel.schema.Schema;
 import org.apache.metamodel.schema.Table;
+import org.apache.metamodel.schema.TableType;
 import org.apache.metamodel.util.BaseObject;
 import org.apache.metamodel.util.EqualsBuilder;
 import org.slf4j.Logger;
@@ -35,12 +36,11 @@ import org.slf4j.LoggerFactory;
  * <ul>
  * <li>column SELECTs (selects a column from a table)</li>
  * <li>column function SELECTs (aggregates the values of a column)</li>
- * <li>expression SELECTs (retrieves data based on an expression (only 
supported
- * for JDBC datastores)</li>
- * <li>expression function SELECTs (retrieves databased on a function and an
- * expression, only COUNT(*) is supported for non-JDBC datastores))</li>
- * <li>SELECTs from subqueries (works just like column selects, but in stead of
- * pointing to a column, it retrieves data from the select item of a 
subquery)</li>
+ * <li>expression SELECTs (retrieves data based on an expression (only 
supported for JDBC datastores)</li>
+ * <li>expression function SELECTs (retrieves databased on a function and an 
expression, only COUNT(*) is supported for
+ * non-JDBC datastores))</li>
+ * <li>SELECTs from subqueries (works just like column selects, but in stead 
of pointing to a column, it retrieves data
+ * from the select item of a subquery)</li>
  * </ul>
  * 
  * @see SelectClause
@@ -98,8 +98,8 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     public static boolean isCountAllItem(SelectItem item) {
-        if (item != null && item.getAggregateFunction() != null && 
item.getAggregateFunction().toString().equals("COUNT")
-                && item.getExpression() == "*") {
+        if (item != null && item.getAggregateFunction() != null
+                && item.getAggregateFunction().toString().equals("COUNT") && 
item.getExpression() == "*") {
             return true;
         }
         return false;
@@ -115,8 +115,7 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Creates a SelectItem that uses a function on a column, for example
-     * SUM(price) or MAX(age)
+     * Creates a SelectItem that uses a function on a column, for example 
SUM(price) or MAX(age)
      * 
      * @param function
      * @param column
@@ -137,8 +136,7 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Creates a SelectItem that references a column from a particular
-     * {@link FromItem}, for example a.price or p.age
+     * Creates a SelectItem that references a column from a particular {@link 
FromItem}, for example a.price or p.age
      * 
      * @param column
      * @param fromItem
@@ -147,7 +145,7 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
         this(null, column, fromItem);
         if (fromItem != null) {
             Table fromItemTable = fromItem.getTable();
-            if (fromItemTable != null) {
+            if (fromItemTable != null && fromItemTable.getType() != 
TableType.ALIAS) {
                 Table columnTable = column.getTable();
                 if (columnTable != null && !columnTable.equals(fromItemTable)) 
{
                     throw new IllegalArgumentException("Column's table '" + 
columnTable.getName()
@@ -158,8 +156,8 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Creates a SelectItem that uses a function on a column from a particular
-     * {@link FromItem}, for example SUM(a.price) or MAX(p.age)
+     * Creates a SelectItem that uses a function on a column from a particular 
{@link FromItem}, for example
+     * SUM(a.price) or MAX(p.age)
      * 
      * @param function
      * @param column
@@ -173,9 +171,8 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Creates a SelectItem that uses a function with parameters on a column
-     * from a particular {@link FromItem}, for example
-     * MAP_VALUE('path.to.value', doc)
+     * Creates a SelectItem that uses a function with parameters on a column 
from a particular {@link FromItem}, for
+     * example MAP_VALUE('path.to.value', doc)
      * 
      * @param function
      * @param functionParameters
@@ -190,8 +187,7 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Creates a SelectItem based on an expression. All expression-based
-     * SelectItems must have aliases.
+     * Creates a SelectItem based on an expression. All expression-based 
SelectItems must have aliases.
      * 
      * @param expression
      * @param alias
@@ -201,8 +197,7 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Creates a SelectItem based on a function and an expression. All
-     * expression-based SelectItems must have aliases.
+     * Creates a SelectItem based on a function and an expression. All 
expression-based SelectItems must have aliases.
      * 
      * @param function
      * @param expression
@@ -219,8 +214,7 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
      * Creates a SelectItem that references another select item in a subquery
      * 
      * @param subQuerySelectItem
-     * @param subQueryFromItem
-     *            the FromItem that holds the sub-query
+     * @param subQueryFromItem the FromItem that holds the sub-query
      */
     public SelectItem(SelectItem subQuerySelectItem, FromItem 
subQueryFromItem) {
         this(null, subQueryFromItem, null, null, null, subQuerySelectItem, 
null, false);
@@ -242,7 +236,7 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
         return this;
     }
 
-    public boolean hasFunction(){
+    public boolean hasFunction() {
         return _function != null;
     }
 
@@ -270,11 +264,9 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * @return if this is a function based SelectItem where function 
calculation
-     *         is allowed to be approximated (if the datastore type has an
-     *         approximate calculation method). Approximated function results
-     *         are as the name implies not exact, but might be valuable as an
-     *         optimization in some cases.
+     * @return if this is a function based SelectItem where function 
calculation is allowed to be approximated (if the
+     *         datastore type has an approximate calculation method). 
Approximated function results are as the name
+     *         implies not exact, but might be valuable as an optimization in 
some cases.
      */
     public boolean isFunctionApproximationAllowed() {
         return _functionApproximationAllowed;
@@ -289,9 +281,8 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Tries to infer the {@link ColumnType} of this {@link SelectItem}. For
-     * expression based select items, this is not possible, and the method will
-     * return null.
+     * Tries to infer the {@link ColumnType} of this {@link SelectItem}. For 
expression based select items, this is not
+     * possible, and the method will return null.
      * 
      * @return
      */
@@ -313,9 +304,9 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Returns an "expression" that this select item represents. Expressions 
are
-     * not necesarily portable across {@link DataContext} implementations, but
-     * may be useful for utilizing database-specific behaviour in certain 
cases.
+     * Returns an "expression" that this select item represents. Expressions 
are not necesarily portable across
+     * {@link DataContext} implementations, but may be useful for utilizing 
database-specific behaviour in certain
+     * cases.
      * 
      * @return
      */
@@ -341,23 +332,19 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * @return the name that this SelectItem can be referenced with, if
-     *         referenced from a super-query. This will usually be the alias,
-     *         but if there is no alias, then the column name will be used.
+     * @return the name that this SelectItem can be referenced with, if 
referenced from a super-query. This will usually
+     *         be the alias, but if there is no alias, then the column name 
will be used.
      */
     public String getSuperQueryAlias() {
         return getSuperQueryAlias(true);
     }
 
     /**
-     * @return the name that this SelectItem can be referenced with, if
-     *         referenced from a super-query. This will usually be the alias,
-     *         but if there is no alias, then the column name will be used.
+     * @return the name that this SelectItem can be referenced with, if 
referenced from a super-query. This will usually
+     *         be the alias, but if there is no alias, then the column name 
will be used.
      * 
-     * @param includeQuotes
-     *            indicates whether or not the output should include quotes, if
-     *            the select item's column has quotes associated (typically
-     *            true, but false if used for presentation)
+     * @param includeQuotes indicates whether or not the output should include 
quotes, if the select item's column has
+     *            quotes associated (typically true, but false if used for 
presentation)
      */
     public String getSuperQueryAlias(boolean includeQuotes) {
         if (_alias != null) {
@@ -391,8 +378,7 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * @return an alias that can be used in WHERE, GROUP BY and ORDER BY 
clauses
-     *         in the same query
+     * @return an alias that can be used in WHERE, GROUP BY and ORDER BY 
clauses in the same query
      */
     public String getSameQueryAlias(boolean includeSchemaInColumnPath) {
         if (_column != null) {
@@ -476,32 +462,38 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     private String getToStringColumnPrefix(boolean includeSchemaInColumnPath) {
-        final StringBuilder sb = new StringBuilder();
         if (_fromItem != null && _fromItem.getAlias() != null) {
-            sb.append(_fromItem.getAlias());
-            sb.append('.');
+            return _fromItem.getAlias() + '.';
+        }
+
+        final Table table;
+        if (_fromItem != null && _fromItem.getTable() != null) {
+            table = _fromItem.getTable();
         } else {
-            final Table table = _column.getTable();
-            String tableLabel;
-            if (_query == null) {
-                tableLabel = null;
-            } else {
-                tableLabel = _query.getFromClause().getAlias(table);
-            }
-            if (table != null) {
-                if (tableLabel == null) {
-                    tableLabel = table.getQuotedName();
-                    if (includeSchemaInColumnPath) {
-                        Schema schema = table.getSchema();
-                        if (schema != null) {
-                            tableLabel = schema.getQuotedName() + "." + 
tableLabel;
-                        }
-                    }
+            table = _column.getTable();
+        }
+        if (table == null) {
+            return "";
+        }
+
+        final StringBuilder sb = new StringBuilder();
+        String tableLabel;
+        if (_query == null) {
+            tableLabel = null;
+        } else {
+            tableLabel = _query.getFromClause().getAlias(table);
+        }
+        if (tableLabel == null) {
+            tableLabel = table.getQuotedName();
+            if (includeSchemaInColumnPath) {
+                Schema schema = table.getSchema();
+                if (schema != null) {
+                    sb.append(schema.getQuotedName() + ".");
                 }
-                sb.append(tableLabel);
-                sb.append('.');
             }
         }
+        sb.append(tableLabel);
+        sb.append('.');
         return sb.toString();
     }
 
@@ -561,13 +553,10 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Creates a clone of the {@link SelectItem} for use within a cloned
-     * {@link Query}.
+     * Creates a clone of the {@link SelectItem} for use within a cloned 
{@link Query}.
      * 
-     * @param clonedQuery
-     *            a new {@link Query} object that represents the clone-to-be of
-     *            a query. It is expected that {@link FromItem}s have already
-     *            been cloned in this {@link Query}.
+     * @param clonedQuery a new {@link Query} object that represents the 
clone-to-be of a query. It is expected that
+     *            {@link FromItem}s have already been cloned in this {@link 
Query}.
      * @return
      */
     protected SelectItem clone(Query clonedQuery) {
@@ -592,8 +581,7 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Creates a copy of the {@link SelectItem}, with a different
-     * {@link FunctionType}.
+     * Creates a copy of the {@link SelectItem}, with a different {@link 
FunctionType}.
      * 
      * @param function
      * @return
@@ -604,8 +592,7 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Creates a copy of the {@link SelectItem}, with a different
-     * {@link #isFunctionApproximationAllowed()} flag set.
+     * Creates a copy of the {@link SelectItem}, with a different {@link 
#isFunctionApproximationAllowed()} flag set.
      * 
      * @param functionApproximationAllowed
      * @return
@@ -616,13 +603,11 @@ public class SelectItem extends BaseObject implements 
QueryItem, Cloneable {
     }
 
     /**
-     * Investigates whether or not this SelectItem references a particular
-     * column. This will search for direct references and indirect references
-     * via subqueries.
+     * Investigates whether or not this SelectItem references a particular 
column. This will search for direct
+     * references and indirect references via subqueries.
      * 
      * @param column
-     * @return a boolean that is true if the specified column is referenced by
-     *         this SelectItem and false otherwise.
+     * @return a boolean that is true if the specified column is referenced by 
this SelectItem and false otherwise.
      */
     public boolean isReferenced(Column column) {
         if (column != null) {

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/schema/AliasTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/AliasTable.java 
b/core/src/main/java/org/apache/metamodel/schema/AliasTable.java
new file mode 100644
index 0000000..8be55dd
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/AliasTable.java
@@ -0,0 +1,82 @@
+/**
+ * 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.schema;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Represents a virtual table that acts as an alias for another table.
+ */
+public class AliasTable extends AbstractTable implements WrappingTable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String name;
+    private final Schema schema;
+    private final Table aliasedTable;
+
+    public AliasTable(String name, Schema schema, Table aliasedTable) {
+        this.name = name;
+        this.schema = schema;
+        this.aliasedTable = aliasedTable;
+    }
+    
+    @Override
+    public Table getWrappedTable() {
+        return aliasedTable;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public List<Column> getColumns() {
+        return aliasedTable.getColumns();
+    }
+
+    @Override
+    public Schema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public TableType getType() {
+        return TableType.ALIAS;
+    }
+
+    @Override
+    public Collection<Relationship> getRelationships() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public String getRemarks() {
+        return null;
+    }
+
+    @Override
+    public String getQuote() {
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/schema/CompositeSchema.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/schema/CompositeSchema.java 
b/core/src/main/java/org/apache/metamodel/schema/CompositeSchema.java
index b48f14b..cbaa801 100644
--- a/core/src/main/java/org/apache/metamodel/schema/CompositeSchema.java
+++ b/core/src/main/java/org/apache/metamodel/schema/CompositeSchema.java
@@ -71,6 +71,7 @@ public class CompositeSchema extends AbstractSchema {
     public List<Table> getTables() {
         return delegates.stream()
                 .flatMap(delegate -> delegate.getTables().stream())
+                .filter(table -> table.getType() != TableType.ALIAS)
                 .collect(Collectors.toList());
     }
 

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/schema/DefaultTableAliasedSchema.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/schema/DefaultTableAliasedSchema.java 
b/core/src/main/java/org/apache/metamodel/schema/DefaultTableAliasedSchema.java
new file mode 100644
index 0000000..9cccc3a
--- /dev/null
+++ 
b/core/src/main/java/org/apache/metamodel/schema/DefaultTableAliasedSchema.java
@@ -0,0 +1,89 @@
+/**
+ * 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.schema;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A special purpose {@link Schema} wrapper which exposes an {@link 
AliasTable} "default_table" for convenience when the
+ * table count is 1.
+ */
+public class DefaultTableAliasedSchema extends AbstractSchema implements 
WrappingSchema {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final String DEFAULT_TABLE_NAME = "default_table";
+
+    public static Schema wrapIfAppropriate(Schema schema) {
+        if (schema.getTableCount() > 1) {
+            return schema;
+        } else {
+            return new DefaultTableAliasedSchema(schema);
+        }
+    }
+
+    private static AliasTable createTable(Schema schema, Table delegateTable) {
+        return new AliasTable(DEFAULT_TABLE_NAME, schema, delegateTable);
+    }
+
+    private final Schema wrappedSchema;
+
+    private DefaultTableAliasedSchema(Schema wrappedSchema) {
+        this.wrappedSchema = wrappedSchema;
+    }
+
+    @Override
+    public Schema getWrappedSchema() {
+        return wrappedSchema;
+    }
+
+    @Override
+    public String getName() {
+        return wrappedSchema.getName();
+    }
+
+    @Override
+    public List<Table> getTables() {
+        List<Table> tables = wrappedSchema.getTables();
+
+        // ensure table size is 1
+        if (tables.size() != 1) {
+            return tables;
+        }
+
+        // ensure no name clashes
+        if (DEFAULT_TABLE_NAME.equals(tables.get(0).getName())) {
+            return tables;
+        }
+
+        // ensure mutability
+        if (!(tables instanceof ArrayList)) {
+            tables = new ArrayList<>(tables);
+        }
+
+        tables.add(createTable(this, tables.get(0)));
+        return tables;
+    }
+
+    @Override
+    public String getQuote() {
+        return wrappedSchema.getQuote();
+    }
+}

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/schema/MutableSchema.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/MutableSchema.java 
b/core/src/main/java/org/apache/metamodel/schema/MutableSchema.java
index 1dbc0c0..b80f5f2 100644
--- a/core/src/main/java/org/apache/metamodel/schema/MutableSchema.java
+++ b/core/src/main/java/org/apache/metamodel/schema/MutableSchema.java
@@ -36,11 +36,11 @@ public class MutableSchema extends AbstractSchema 
implements Serializable,
        private static final long serialVersionUID = 4465197783868238863L;
 
        private String _name;
-       private final List<MutableTable> _tables;
+       private final List<Table> _tables;
 
        public MutableSchema() {
                super();
-               _tables = new ArrayList<MutableTable>();
+               _tables = new ArrayList<Table>();
        }
 
        public MutableSchema(String name) {
@@ -48,7 +48,7 @@ public class MutableSchema extends AbstractSchema implements 
Serializable,
                _name = name;
        }
 
-       public MutableSchema(String name, MutableTable... tables) {
+       public MutableSchema(String name, Table... tables) {
                this(name);
                setTables(tables);
        }
@@ -69,17 +69,17 @@ public class MutableSchema extends AbstractSchema 
implements Serializable,
        }
 
 
-       public MutableSchema setTables(Collection<? extends MutableTable> 
tables) {
+       public MutableSchema setTables(Collection<? extends Table> tables) {
            clearTables();
-               for (MutableTable table : tables) {
+               for (Table table : tables) {
                        _tables.add(table);
                }
                return this;
        }
 
-       public MutableSchema setTables(MutableTable... tables) {
+       public MutableSchema setTables(Table... tables) {
            clearTables();
-               for (MutableTable table : tables) {
+               for (Table table : tables) {
                        _tables.add(table);
                }
                return this;
@@ -90,7 +90,7 @@ public class MutableSchema extends AbstractSchema implements 
Serializable,
            return this;
        }
 
-       public MutableSchema addTable(MutableTable table) {
+       public MutableSchema addTable(Table table) {
                _tables.add(table);
                return this;
        }

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/schema/WrappingSchema.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/WrappingSchema.java 
b/core/src/main/java/org/apache/metamodel/schema/WrappingSchema.java
new file mode 100644
index 0000000..f1809e5
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/WrappingSchema.java
@@ -0,0 +1,33 @@
+/**
+ * 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.schema;
+
+/**
+ * Sub-interface for {@link Schema}s that wrap other {@link Schema}s, 
typically to apply some client-side enhancement
+ * logic.
+ */
+public interface WrappingSchema extends Schema {
+
+    /**
+     * Gets the {@link Schema} that is wrapped by this {@link WrappingSchema}.
+     * 
+     * @return
+     */
+    public Schema getWrappedSchema();
+}

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/main/java/org/apache/metamodel/schema/WrappingTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/WrappingTable.java 
b/core/src/main/java/org/apache/metamodel/schema/WrappingTable.java
new file mode 100644
index 0000000..b147a2f
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/schema/WrappingTable.java
@@ -0,0 +1,33 @@
+/**
+ * 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.schema;
+
+/**
+ * Sub-interface for {@link Table}s that wrap other {@link Table}s, typically 
to apply some client-side enhancement
+ * logic.
+ */
+public interface WrappingTable extends Table {
+
+    /**
+     * Gets the {@link Table} that is wrapped by this {@link WrappingTable}.
+     * 
+     * @return
+     */
+    public Table getWrappedTable();
+}

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/test/java/org/apache/metamodel/MockDataContext.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/MockDataContext.java 
b/core/src/test/java/org/apache/metamodel/MockDataContext.java
index 0c217f2..0a6cd72 100644
--- a/core/src/test/java/org/apache/metamodel/MockDataContext.java
+++ b/core/src/test/java/org/apache/metamodel/MockDataContext.java
@@ -45,6 +45,7 @@ public class MockDataContext extends 
QueryPostprocessDataContext {
     private final String _value;
 
     public MockDataContext(String schemaName, String tableName, String value) {
+        super(true);
         _schemaName = schemaName;
         _tableName = tableName;
         _value = value;

http://git-wip-us.apache.org/repos/asf/metamodel/blob/fe9ab604/core/src/test/java/org/apache/metamodel/MockUpdateableDataContext.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/metamodel/MockUpdateableDataContext.java 
b/core/src/test/java/org/apache/metamodel/MockUpdateableDataContext.java
index 4e6563a..4d06d5a 100644
--- a/core/src/test/java/org/apache/metamodel/MockUpdateableDataContext.java
+++ b/core/src/test/java/org/apache/metamodel/MockUpdateableDataContext.java
@@ -51,8 +51,13 @@ public class MockUpdateableDataContext extends 
QueryPostprocessDataContext imple
 
     private final MutableTable _table;
     private final MutableSchema _schema;
-
+    
     public MockUpdateableDataContext() {
+        this(true);
+    }
+
+    public MockUpdateableDataContext(boolean addDefaultTableAlias) {
+        super(addDefaultTableAlias);
         _values.add(new Object[] { "1", "hello" });
         _values.add(new Object[] { "2", "there" });
         _values.add(new Object[] { "3", "world" });
@@ -70,6 +75,9 @@ public class MockUpdateableDataContext extends 
QueryPostprocessDataContext imple
 
     @Override
     protected DataSet materializeMainSchemaTable(Table table, List<Column> 
columns, int maxRows) {
+        if (table != _table) {
+            throw new IllegalArgumentException("Unknown table: " + table);
+        }
 
         List<Row> rows = new ArrayList<Row>();
         List<SelectItem> items = 
columns.stream().map(SelectItem::new).collect(Collectors.toList());
@@ -112,6 +120,9 @@ public class MockUpdateableDataContext extends 
QueryPostprocessDataContext imple
             @Override
             public RowDeletionBuilder deleteFrom(Table table) throws 
IllegalArgumentException, IllegalStateException,
                     UnsupportedOperationException {
+                if (table != _table) {
+                    throw new IllegalArgumentException("Unknown table: " + 
table);
+                }
                 return new AbstractRowDeletionBuilder(table) {
                     @Override
                     public void execute() throws MetaModelException {
@@ -123,6 +134,9 @@ public class MockUpdateableDataContext extends 
QueryPostprocessDataContext imple
             @Override
             public RowInsertionBuilder insertInto(Table table) throws 
IllegalArgumentException, IllegalStateException,
                     UnsupportedOperationException {
+                if (table != _table) {
+                    throw new IllegalArgumentException("Unknown table: " + 
table);
+                }
                 return new AbstractRowInsertionBuilder<UpdateCallback>(this, 
table) {
 
                     @Override

Reply via email to