You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metamodel.apache.org by ka...@apache.org on 2013/07/19 11:33:07 UTC

[24/61] [partial] Hard rename of all 'org/eobjects' folders to 'org/apache'.

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/query/SelectItemTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/SelectItemTest.java b/core/src/test/java/org/apache/metamodel/query/SelectItemTest.java
new file mode 100644
index 0000000..5896d9a
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/query/SelectItemTest.java
@@ -0,0 +1,99 @@
+/**
+ * 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.eobjects.metamodel.query;
+
+import org.eobjects.metamodel.MetaModelTestCase;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.MutableColumn;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+
+public class SelectItemTest extends MetaModelTestCase {
+
+    private Schema _schema = getExampleSchema();
+
+    public void testSelectColumnInFromItem() throws Exception {
+        final Table projectTable = _schema.getTableByName(TABLE_PROJECT);
+        final Column column1 = projectTable.getColumns()[0];
+        final Column column2 = projectTable.getColumns()[1];
+
+        Query q = new Query().from(projectTable, "a").from(projectTable, "b");
+        q.select(column1, q.getFromClause().getItem(1));
+        q.select(column2, q.getFromClause().getItem(0));
+
+        assertEquals("SELECT b.project_id, a.name FROM MetaModelSchema.project a, MetaModelSchema.project b", q.toSql());
+    }
+    
+    public void testToSql() throws Exception {
+        SelectItem selectItem = new SelectItem(_schema.getTableByName(TABLE_PROJECT).getColumns()[0]);
+        assertEquals("project.project_id", selectItem.toSql());
+    }
+
+    public void testSubQuerySelectItem() throws Exception {
+        Table projectTable = _schema.getTableByName(TABLE_PROJECT);
+        Table roleTable = _schema.getTableByName(TABLE_ROLE);
+
+        Column projectIdColumn = projectTable.getColumnByName(COLUMN_PROJECT_PROJECT_ID);
+
+        FromItem leftSide = new FromItem(projectTable);
+        leftSide.setAlias("a");
+        SelectItem[] leftOn = new SelectItem[] { new SelectItem(projectIdColumn) };
+
+        Query subQuery = new Query();
+        FromItem subQueryFrom = new FromItem(roleTable);
+        subQueryFrom.setAlias("c");
+        subQuery.from(subQueryFrom);
+        Column[] columns = roleTable.getColumns();
+        subQuery.select(columns);
+
+        SelectItem subQuerySelectItem = subQuery.getSelectClause().getSelectItem(columns[1]);
+        FromItem rightSide = new FromItem(subQuery);
+        rightSide.setAlias("b");
+        SelectItem[] rightOn = new SelectItem[] { subQuerySelectItem };
+        FromItem from = new FromItem(JoinType.LEFT, leftSide, rightSide, leftOn, rightOn);
+
+        assertEquals(
+                "MetaModelSchema.project a LEFT JOIN (SELECT c.contributor_id, c.project_id, c.name FROM MetaModelSchema.role c) b ON a.project_id = b.project_id",
+                from.toString());
+
+        Query q = new Query();
+        q.from(from);
+        try {
+            new SelectItem(subQuerySelectItem, from);
+            fail("Exception should have been thrown!");
+        } catch (IllegalArgumentException e) {
+            assertEquals("Only sub-query based FromItems allowed.", e.getMessage());
+        }
+
+        q.select(new SelectItem(subQuerySelectItem, rightSide));
+        assertEquals(
+                "SELECT b.project_id FROM MetaModelSchema.project a LEFT JOIN (SELECT c.contributor_id, c.project_id, c.name FROM MetaModelSchema.role c) b ON a.project_id = b.project_id",
+                q.toString());
+    }
+
+    public void testGetSuperQueryAlias() throws Exception {
+        SelectItem item = new SelectItem(FunctionType.COUNT, "*", "").setAlias(null);
+        assertEquals("COUNT(*)", item.getSameQueryAlias());
+        assertEquals("COUNT(*)", item.getSuperQueryAlias());
+        
+        item = new SelectItem(FunctionType.SUM, new MutableColumn("foo"));
+        assertEquals("SUM(foo)", item.getSameQueryAlias());
+        assertEquals("SUM(foo)", item.getSuperQueryAlias());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/query/builder/GroupedQueryBuilderImplTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/builder/GroupedQueryBuilderImplTest.java b/core/src/test/java/org/apache/metamodel/query/builder/GroupedQueryBuilderImplTest.java
new file mode 100644
index 0000000..4b3b399
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/query/builder/GroupedQueryBuilderImplTest.java
@@ -0,0 +1,108 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+import org.eobjects.metamodel.AbstractDataContext;
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.data.DataSet;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.MutableColumn;
+import org.eobjects.metamodel.schema.MutableTable;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+
+public class GroupedQueryBuilderImplTest extends TestCase {
+
+	public void testFindColumnWithAlias() throws Exception {
+		DataContext dataContext = EasyMock.createMock(DataContext.class);
+
+		MutableTable table1 = new MutableTable("foo");
+		table1.addColumn(new MutableColumn("col1").setTable(table1));
+		table1.addColumn(new MutableColumn("col2").setTable(table1));
+		table1.addColumn(new MutableColumn("col3").setTable(table1));
+
+		MutableTable table2 = new MutableTable("bar");
+		table2.addColumn(new MutableColumn("col1").setTable(table2));
+		table2.addColumn(new MutableColumn("col2").setTable(table2));
+		table2.addColumn(new MutableColumn("col3").setTable(table2));
+
+		Query query = new Query().from(table1, "f").from(table2, "b");
+		GroupedQueryBuilderImpl gqbi = new GroupedQueryBuilderImpl(dataContext,
+				query);
+
+		Column col = gqbi.findColumn("b.col2");
+		assertEquals("bar.col2", col.getQualifiedLabel());
+
+		col = gqbi.findColumn("f.col2");
+		assertEquals("foo.col2", col.getQualifiedLabel());
+
+		try {
+			col = gqbi.findColumn("f.col4");
+			fail("Exception expected");
+		} catch (IllegalArgumentException e) {
+			assertEquals("Could not find column: f.col4", e.getMessage());
+		}
+	}
+
+	// test-case to recreate the problems reported at
+	// http://eobjects.org/trac/discussion/7/134
+	public void testLeftJoinQueries() throws Exception {
+		DataContext dc = new AbstractDataContext() {
+
+			@Override
+			public DataSet executeQuery(Query query) throws MetaModelException {
+				throw new UnsupportedOperationException();
+			}
+
+			@Override
+			protected String[] getSchemaNamesInternal() {
+				throw new UnsupportedOperationException();
+			}
+
+			@Override
+			protected String getDefaultSchemaName() {
+				throw new UnsupportedOperationException();
+			}
+
+			@Override
+			protected Schema getSchemaByNameInternal(String name) {
+				throw new UnsupportedOperationException();
+			}
+		};
+		Table tableAB = new MutableTable("tableAB");
+		Table tableC = new MutableTable("tableC");
+
+		Column colA = new MutableColumn("colA", null, tableAB, 0, true);
+		Column colB = new MutableColumn("colB", null, tableAB, 1, true);
+		Column colC = new MutableColumn("colC", null, tableC, 0, true);
+
+		Query q = dc.query().from(tableAB).leftJoin(tableC).on(colB, colC)
+				.select(colA).as("a").select(colB).as("b").select(colC).as("c")
+				.toQuery();
+
+		assertEquals(
+				"SELECT tableAB.colA AS a, tableAB.colB AS b, tableC.colC AS c FROM tableAB LEFT JOIN tableC ON tableAB.colB = tableC.colC",
+				q.toSql());
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/query/builder/SyntaxExamplesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/builder/SyntaxExamplesTest.java b/core/src/test/java/org/apache/metamodel/query/builder/SyntaxExamplesTest.java
new file mode 100644
index 0000000..0f04584
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/query/builder/SyntaxExamplesTest.java
@@ -0,0 +1,80 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import junit.framework.TestCase;
+
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.MockDataContext;
+import org.eobjects.metamodel.query.FunctionType;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.MutableSchema;
+import org.eobjects.metamodel.schema.MutableTable;
+import org.eobjects.metamodel.schema.Table;
+
+public class SyntaxExamplesTest extends TestCase {
+
+    private DataContext dc;
+    private Table table1;
+    private Table table2;
+    private Column col1;
+    private Column col2;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        dc = new MockDataContext("sch", "tab1", "foo");
+        MutableSchema schema = (MutableSchema) dc.getDefaultSchema();
+        table1 = schema.getTables()[0];
+        schema.addTable(new MutableTable("tab2").setSchema(schema));
+        table2 = schema.getTableByName("tab2");
+        col1 = table1.getColumns()[0];
+        col2 = table1.getColumns()[1];
+    }
+
+    public void testSchema() throws Exception {
+        assertEquals("tab1", table1.getName());
+        assertEquals("sch.tab1", table1.getQualifiedLabel());
+    }
+
+    public void testFromAlias() throws Exception {
+        dc.query().from(table1).as("t");
+    }
+
+    public void testFromJoin() throws Exception {
+        dc.query().from(table1).innerJoin(table2).on(col1, col2).select(col1);
+    }
+
+    public void testWhereOr() throws Exception {
+        dc.query().from(table1).as("t").select(col2).where(col1).isNotNull().or(col1).isNull().orderBy(col1).asc();
+    }
+
+    public void testGroupBy() throws Exception {
+        dc.query().from(table1).selectCount().select(col1).groupBy(col1).having(FunctionType.SUM, col1).greaterThan(3)
+                .orderBy(col1).asc();
+    }
+
+    public void testMultipleTables() throws Exception {
+        Query q = dc.query().from(table1).as("t1").and(table2).as("t2").select(col1).where(col1).greaterThan(col2)
+                .orderBy(col2).desc().toQuery();
+        assertEquals("SELECT t1.foo FROM sch.tab1 t1, sch.tab2 t2 " + "WHERE t1.foo > t1.bar ORDER BY t1.bar DESC",
+                q.toSql());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/query/builder/WhereBuilderImplTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/builder/WhereBuilderImplTest.java b/core/src/test/java/org/apache/metamodel/query/builder/WhereBuilderImplTest.java
new file mode 100644
index 0000000..4d45f61
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/query/builder/WhereBuilderImplTest.java
@@ -0,0 +1,81 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.schema.ColumnType;
+import org.eobjects.metamodel.schema.MutableColumn;
+import junit.framework.TestCase;
+
+public class WhereBuilderImplTest extends TestCase {
+
+	private MutableColumn col1 = new MutableColumn("col1", ColumnType.BOOLEAN);
+	private MutableColumn col2 = new MutableColumn("col2");
+	private WhereBuilderImpl whereBuilder;
+	private Query query;
+
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		query = new Query();
+		GroupedQueryBuilder queryBuilder = new GroupedQueryBuilderImpl(null,
+				query);
+		whereBuilder = new WhereBuilderImpl(col1, query, queryBuilder);
+	}
+
+	public void testOr() throws Exception {
+		whereBuilder.eq(true).or(col2).like("%testcase%");
+
+		assertEquals(" WHERE (col1 = TRUE OR col2 LIKE '%testcase%')",
+				query.toSql());
+	}
+
+	public void testAnd() throws Exception {
+		whereBuilder.differentFrom(true).and(col2).eq(1).or(col2).eq(2)
+				.or(col2).eq(3).and(new MutableColumn("col3")).eq(4);
+
+		assertEquals(
+				" WHERE col1 <> TRUE AND (col2 = 1 OR col2 = 2 OR col2 = 3) AND col3 = 4",
+				query.toSql());
+	}
+
+	public void testInStringArray() throws Exception {
+		whereBuilder.eq(true).or(col2).in("foo", "bar");
+
+		assertEquals(" WHERE (col1 = TRUE OR col2 IN ('foo' , 'bar'))",
+				query.toSql());
+	}
+
+	public void testInNumberArray() throws Exception {
+		whereBuilder.eq(true).or(col2).in(3, 1);
+
+		assertEquals(" WHERE (col1 = TRUE OR col2 IN (3 , 1))", query.toSql());
+	}
+
+	public void testInCollection() throws Exception {
+		Collection<?> col = Arrays.asList("foo", "bar");
+		whereBuilder.eq(true).or(col2).in(col);
+
+		assertEquals(" WHERE (col1 = TRUE OR col2 IN ('foo' , 'bar'))",
+				query.toSql());
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/query/parser/QueryParserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/parser/QueryParserTest.java b/core/src/test/java/org/apache/metamodel/query/parser/QueryParserTest.java
new file mode 100644
index 0000000..786b79e
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/query/parser/QueryParserTest.java
@@ -0,0 +1,320 @@
+/**
+ * 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.eobjects.metamodel.query.parser;
+
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.MetaModelHelper;
+import org.eobjects.metamodel.MockDataContext;
+import org.eobjects.metamodel.query.FilterClause;
+import org.eobjects.metamodel.query.FilterItem;
+import org.eobjects.metamodel.query.FromItem;
+import org.eobjects.metamodel.query.OperatorType;
+import org.eobjects.metamodel.query.OrderByItem;
+import org.eobjects.metamodel.query.OrderByItem.Direction;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.query.SelectItem;
+import org.eobjects.metamodel.schema.ColumnType;
+import org.eobjects.metamodel.schema.MutableColumn;
+
+public class QueryParserTest extends TestCase {
+
+    private MockDataContext dc;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        dc = new MockDataContext("sch", "tbl", "foo");
+
+        // set 'baz' column to an integer column (to influence query generation)
+        MutableColumn col = (MutableColumn) dc.getColumnByQualifiedLabel("tbl.baz");
+        col.setType(ColumnType.INTEGER);
+    };
+
+    public void testQueryInLowerCase() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc,
+                "select a.foo as f from sch.tbl a inner join sch.tbl b on a.foo=b.foo order by a.foo asc");
+        assertEquals("SELECT a.foo AS f FROM sch.tbl a INNER JOIN sch.tbl b ON a.foo = b.foo ORDER BY a.foo ASC",
+                q.toSql());
+    }
+
+    public void testSelectEverythingFromTable() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT * FROM sch.tbl");
+        assertEquals("SELECT tbl.foo, tbl.bar, tbl.baz FROM sch.tbl", q.toSql());
+    }
+
+    public void testSelectEverythingFromJoin() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT * FROM sch.tbl a INNER JOIN sch.tbl b ON a.foo = b.foo");
+        assertEquals(
+                "SELECT a.foo, a.bar, a.baz, b.foo, b.bar, b.baz FROM sch.tbl a INNER JOIN sch.tbl b ON a.foo = b.foo",
+                q.toSql());
+
+        q = MetaModelHelper.parseQuery(dc, "SELECT a.foo, b.* FROM sch.tbl a INNER JOIN sch.tbl b ON a.foo = b.foo");
+        assertEquals("SELECT a.foo, b.foo, b.bar, b.baz FROM sch.tbl a INNER JOIN sch.tbl b ON a.foo = b.foo",
+                q.toSql());
+    }
+
+    public void testSelectColumnWithDotInName() throws Exception {
+        MutableColumn col = (MutableColumn) dc.getTableByQualifiedLabel("tbl").getColumn(0);
+        col.setName("fo.o");
+
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT fo.o AS f FROM sch.tbl");
+        assertEquals("SELECT tbl.fo.o AS f FROM sch.tbl", q.toSql());
+    }
+
+    public void testSelectAlias() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT foo AS f FROM sch.tbl");
+        assertEquals("SELECT tbl.foo AS f FROM sch.tbl", q.toSql());
+
+        q = MetaModelHelper.parseQuery(dc, "SELECT a.foo AS foobarbaz FROM sch.tbl a WHERE foobarbaz = '123'");
+        assertEquals("SELECT a.foo AS foobarbaz FROM sch.tbl a WHERE foobarbaz = '123'", q.toSql());
+    }
+
+    public void testSelectDistinct() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT DISTINCT foo, bar AS f FROM sch.tbl");
+        assertEquals("SELECT DISTINCT tbl.foo, tbl.bar AS f FROM sch.tbl", q.toSql());
+    }
+
+    public void testSimpleSelectFrom() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT foo\nFROM sch.tbl");
+        assertEquals("SELECT tbl.foo FROM sch.tbl", q.toSql());
+
+        assertEquals(1, q.getFromClause().getItemCount());
+        FromItem fromItem = q.getFromClause().getItem(0);
+        assertNull("FROM item was an expression based item, which indicates it was not parsed",
+                fromItem.getExpression());
+        assertNotNull(fromItem.getTable());
+        assertEquals("tbl", fromItem.getTable().getName());
+
+        assertEquals(1, q.getSelectClause().getItemCount());
+        SelectItem selectItem = q.getSelectClause().getItem(0);
+        assertNull("SELECT item was an expression based item, which indicates it was not parsed",
+                selectItem.getExpression());
+        assertNotNull(selectItem.getColumn());
+        assertEquals("foo", selectItem.getColumn().getName());
+
+        assertNull(q.getFirstRow());
+        assertNull(q.getMaxRows());
+    }
+
+    public void testCarthesianProduct() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc,
+                "  SELECT a.foo,b.bar FROM      sch.tbl a, sch.tbl b \t WHERE a.foo = b.foo");
+        assertEquals("SELECT a.foo, b.bar FROM sch.tbl a, sch.tbl b WHERE a.foo = b.foo", q.toSql());
+
+        List<FromItem> fromItems = q.getFromClause().getItems();
+        assertNotNull(fromItems.get(0).getTable());
+        assertNotNull(fromItems.get(1).getTable());
+
+        List<FilterItem> whereItems = q.getWhereClause().getItems();
+        assertNotNull(whereItems.get(0).getSelectItem().getColumn());
+        assertNotNull(whereItems.get(0).getSelectItem().getFromItem().getTable());
+    }
+
+    public void testJoin() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc,
+                "SELECT a.foo,b.bar FROM sch.tbl a INNER JOIN sch.tbl b ON a.foo = b.foo");
+        assertEquals("SELECT a.foo, b.bar FROM sch.tbl a INNER JOIN sch.tbl b ON a.foo = b.foo", q.toSql());
+
+        q = MetaModelHelper.parseQuery(dc,
+                "SELECT COUNT(*) FROM sch.tbl a LEFT JOIN sch.tbl b ON a.foo = b.foo AND a.bar = b.baz");
+        assertEquals("SELECT COUNT(*) FROM sch.tbl a LEFT JOIN sch.tbl b ON a.foo = b.foo AND a.bar = b.baz", q.toSql());
+    }
+
+    public void testSimpleSelectFromWhere() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE bar = 'baz' AND baz > 5");
+        assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.bar = 'baz' AND tbl.baz > 5", q.toSql());
+
+        FilterClause whereClause = q.getWhereClause();
+        assertEquals(2, whereClause.getItemCount());
+        assertNull("WHERE item was an expression based item, which indicates it was not parsed", whereClause.getItem(0)
+                .getExpression());
+        assertEquals(2, whereClause.getItemCount());
+        assertNull("WHERE item was an expression based item, which indicates it was not parsed", whereClause.getItem(1)
+                .getExpression());
+
+        assertEquals("baz", whereClause.getItem(0).getOperand());
+        assertEquals(Integer.class, whereClause.getItem(1).getOperand().getClass());
+    }
+    
+    public void testWhereStringEscaped() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE bar = 'ba\\'z'");
+        assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.bar = 'ba'z'", q.toSql());
+    }
+    
+    public void testWhereOperandIsBoolean() throws Exception {
+     // set 'baz' column to an integer column (to influence query generation)
+        MutableColumn col = (MutableColumn) dc.getColumnByQualifiedLabel("tbl.baz");
+        col.setType(ColumnType.BOOLEAN);
+        
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE baz = TRUE");
+        assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.baz = TRUE", q.toSql());
+    }
+    
+    public void testWhereOperandIsDate() throws Exception {
+        // set 'baz' column to an integer column (to influence query generation)
+           MutableColumn col = (MutableColumn) dc.getColumnByQualifiedLabel("tbl.baz");
+           col.setType(ColumnType.TIME);
+           
+           Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE baz = 10:24");
+           assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.baz = TIME '10:24:00'", q.toSql());
+       }
+
+    public void testCoumpoundWhereClause() throws Exception {
+        Query q = MetaModelHelper
+                .parseQuery(dc, "SELECT foo FROM sch.tbl WHERE (bar = 'baz' OR (baz > 5 AND baz < 7))");
+        assertEquals("SELECT tbl.foo FROM sch.tbl WHERE (tbl.bar = 'baz' OR (tbl.baz > 5 AND tbl.baz < 7))", q.toSql());
+
+        FilterClause wc = q.getWhereClause();
+        assertEquals(1, wc.getItemCount());
+        FilterItem item = wc.getItem(0);
+        assertTrue(item.isCompoundFilter());
+
+        FilterItem[] childItems = item.getChildItems();
+        assertEquals(2, childItems.length);
+
+        FilterItem bazConditions = childItems[1];
+        assertTrue(bazConditions.isCompoundFilter());
+    }
+
+    public void testWhereSomethingIsNull() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE bar IS NULL");
+        assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.bar IS NULL", q.toSql());
+
+        assertEquals(1, q.getWhereClause().getItemCount());
+        assertNull("WHERE item was an expression based item, which indicates it was not parsed", q.getWhereClause()
+                .getItem(0).getExpression());
+        assertNull(q.getWhereClause().getItem(0).getOperand());
+        assertEquals(OperatorType.EQUALS_TO, q.getWhereClause().getItem(0).getOperator());
+    }
+
+    public void testWhereSomethingIsNotNull() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE bar IS NOT NULL");
+        assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.bar IS NOT NULL", q.toSql());
+
+        assertEquals(1, q.getWhereClause().getItemCount());
+        assertNull("WHERE item was an expression based item, which indicates it was not parsed", q.getWhereClause()
+                .getItem(0).getExpression());
+        assertNull(q.getWhereClause().getItem(0).getOperand());
+        assertEquals(OperatorType.DIFFERENT_FROM, q.getWhereClause().getItem(0).getOperator());
+    }
+
+    public void testLimitAndOffset() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl LIMIT 1234 OFFSET 5");
+        assertEquals("SELECT tbl.foo FROM sch.tbl", q.toSql());
+        assertEquals(1234, q.getMaxRows().intValue());
+        assertEquals(6, q.getFirstRow().intValue());
+    }
+
+    public void testWhereIn() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT foo FROM sch.tbl WHERE foo IN ('a','b',5)");
+        assertEquals("SELECT tbl.foo FROM sch.tbl WHERE tbl.foo IN ('a' , 'b' , '5')", q.toSql());
+
+        FilterItem whereItem = q.getWhereClause().getItem(0);
+        assertEquals(OperatorType.IN, whereItem.getOperator());
+        Object operand = whereItem.getOperand();
+        assertTrue(operand instanceof List);
+        assertEquals("a", ((List<?>) operand).get(0));
+        assertEquals("b", ((List<?>) operand).get(1));
+        assertEquals(5, ((List<?>) operand).get(2));
+    }
+
+    public void testSimpleSubQuery() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT f.foo AS fo FROM (SELECT * FROM sch.tbl) f");
+        assertEquals("SELECT f.foo AS fo FROM (SELECT tbl.foo, tbl.bar, tbl.baz FROM sch.tbl) f", q.toSql());
+    }
+    
+    public void testSelectEverythingFromSubQuery() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc, "SELECT * FROM (SELECT foo, bar FROM sch.tbl) f");
+        assertEquals("SELECT f.foo, f.bar FROM (SELECT tbl.foo, tbl.bar FROM sch.tbl) f", q.toSql());
+    }
+
+    public void testGetIndicesVanillaScenario() throws Exception {
+        QueryParser qp = new QueryParser(dc, "SELECT ... FROM ... BAR BAZ");
+        assertEquals("[0, 7]", Arrays.toString(qp.indexesOf("SELECT ", null)));
+        assertEquals("[10, 16]", Arrays.toString(qp.indexesOf(" FROM ", null)));
+    }
+    
+    public void testGetIndicesIgnoreWhiteSpaceAndCaseDifferences() throws Exception {
+        QueryParser qp = new QueryParser(dc, " \t\r\n select ... from ... BAR BAZ");
+        assertEquals("[0, 7]", Arrays.toString(qp.indexesOf("SELECT ", null)));
+        assertEquals("[10, 16]", Arrays.toString(qp.indexesOf(" FROM ", null)));
+    }
+
+    public void testInvalidQueries() throws Exception {
+        try {
+            MetaModelHelper.parseQuery(dc, "foobar");
+            fail("Exception expected");
+        } catch (MetaModelException e) {
+            assertEquals("SELECT not found in query: foobar", e.getMessage());
+        }
+
+        try {
+            MetaModelHelper.parseQuery(dc, "SELECT foobar");
+            fail("Exception expected");
+        } catch (MetaModelException e) {
+            assertEquals("FROM not found in query: SELECT foobar", e.getMessage());
+        }
+    }
+
+    public void testFullQuery() throws Exception {
+        Query q = MetaModelHelper.parseQuery(dc,
+                "SELECT foo, COUNT(* ), MAX( baz ) FROM sch.tbl WHERE bar = 'baz' AND foo = bar AND baz > 5 "
+                        + "GROUP BY foo HAVING COUNT(*) > 2 ORDER BY foo LIMIT 20 OFFSET 10");
+        assertEquals(
+                "SELECT tbl.foo, COUNT(*), MAX(tbl.baz) FROM sch.tbl WHERE tbl.bar = 'baz' AND tbl.foo = tbl.bar AND tbl.baz > 5 "
+                        + "GROUP BY tbl.foo HAVING COUNT(*) > 2 ORDER BY tbl.foo ASC", q.toSql());
+        assertEquals(20, q.getMaxRows().intValue());
+        assertEquals(11, q.getFirstRow().intValue());
+
+        // SELECT ...
+        // tbl.foo
+        assertNotNull("SelectItem 1 should be a column", q.getSelectClause().getItem(0).getColumn());
+
+        // COUNT(*)
+        assertNotNull("SelectItem 2 should be a Function", q.getSelectClause().getItem(1).getFunction());
+        assertNotNull("SelectItem 2 should be a Function of '*'", q.getSelectClause().getItem(1).getExpression());
+
+        // MAX(tbl.baz)
+        assertNotNull("SelectItem 3 should be a Function", q.getSelectClause().getItem(2).getFunction());
+        assertNotNull("SelectItem 4 should be a Function of a column", q.getSelectClause().getItem(2).getColumn());
+
+        // FROM tbl.foo
+        assertNotNull(q.getFromClause().getItem(0).getTable());
+
+        // GROUP BY tbl.foo
+        assertNotNull(q.getGroupByClause().getItem(0).getSelectItem().getColumn());
+
+        // HAVING COUNT(*) > 2
+        FilterItem havingItem = q.getHavingClause().getItem(0);
+        assertNull(havingItem.getExpression());
+        assertNotNull(havingItem.getSelectItem().getFunction());
+        assertEquals("*", havingItem.getSelectItem().getExpression());
+
+        // ORDER BY tbl.foo ASC
+        OrderByItem orderByItem = q.getOrderByClause().getItem(0);
+        assertNull(orderByItem.getSelectItem().getExpression());
+        assertNotNull(orderByItem.getSelectItem().getColumn());
+        assertEquals(Direction.ASC, orderByItem.getDirection());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/query/parser/QueryPartParserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/parser/QueryPartParserTest.java b/core/src/test/java/org/apache/metamodel/query/parser/QueryPartParserTest.java
new file mode 100644
index 0000000..0066f9c
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/query/parser/QueryPartParserTest.java
@@ -0,0 +1,110 @@
+/**
+ * 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.eobjects.metamodel.query.parser;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public class QueryPartParserTest extends TestCase {
+
+    public void testParseNone() throws Exception {
+        QueryPartCollectionProcessor itemParser = new QueryPartCollectionProcessor();
+
+        new QueryPartParser(itemParser, " ", ",").parse();
+
+        List<String> items = itemParser.getTokens();
+        assertEquals(0, items.size());
+        assertEquals("[]", items.toString());
+    }
+
+    public void testParseSingle() throws Exception {
+        QueryPartCollectionProcessor itemParser = new QueryPartCollectionProcessor();
+
+        new QueryPartParser(itemParser, "foo ", ",").parse();
+
+        List<String> items = itemParser.getTokens();
+        assertEquals(1, items.size());
+        assertEquals("[foo]", items.toString());
+        assertEquals("[null]", itemParser.getDelims().toString());
+    }
+
+    public void testParseMultiple() throws Exception {
+        QueryPartCollectionProcessor itemParser = new QueryPartCollectionProcessor();
+
+        new QueryPartParser(itemParser, "foo , bar", ",").parse();
+
+        List<String> items = itemParser.getTokens();
+        assertEquals(2, items.size());
+        assertEquals("[foo, bar]", items.toString());
+    }
+
+    public void testParseWithParenthesis() throws Exception {
+        QueryPartCollectionProcessor itemParser = new QueryPartCollectionProcessor();
+
+        new QueryPartParser(itemParser, "foo , bar (a,b,c),(doh)", ",").parse();
+
+        List<String> items = itemParser.getTokens();
+        assertEquals("[foo, bar (a,b,c), (doh)]", items.toString());
+        assertEquals(3, items.size());
+    }
+
+    public void testMultipleDelims() throws Exception {
+        QueryPartCollectionProcessor itemParser = new QueryPartCollectionProcessor();
+
+        new QueryPartParser(itemParser, "foo AND bar OR baz AND (foo( AND bar) OR baz)", " AND ", " OR ").parse();
+
+        List<String> items = itemParser.getTokens();
+        assertEquals(4, items.size());
+        assertEquals("[foo, bar, baz, (foo( AND bar) OR baz)]", items.toString());
+        assertEquals("[null,  AND ,  OR ,  AND ]", itemParser.getDelims().toString());
+    }
+
+    public void testEmptyClause() throws Exception {
+        QueryPartCollectionProcessor itemParser = new QueryPartCollectionProcessor();
+
+        new QueryPartParser(itemParser, "", ",").parse();
+        assertEquals(0, itemParser.getTokens().size());
+    }
+
+    public void testEmptyParenthesis() throws Exception {
+        QueryPartCollectionProcessor itemParser = new QueryPartCollectionProcessor();
+
+        new QueryPartParser(itemParser, "()", ",").parse();
+        assertEquals(0, itemParser.getTokens().size());
+    }
+    
+    public void testMultiParenthesisLevels() throws Exception {
+        QueryPartCollectionProcessor itemParser = new QueryPartCollectionProcessor();
+
+        new QueryPartParser(itemParser, "(((Hello world)))", ",").parse();
+        assertEquals(1, itemParser.getTokens().size());
+        assertEquals("Hello world", itemParser.getTokens().get(0));
+    }
+
+    public void testOuterParenthesis() throws Exception {
+        QueryPartCollectionProcessor itemParser = new QueryPartCollectionProcessor();
+
+        new QueryPartParser(itemParser, "(foo,bar)", ",").parse();
+
+        List<String> items = itemParser.getTokens();
+        assertEquals(2, items.size());
+        assertEquals("[foo, bar]", items.toString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/ColumnTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/ColumnTypeTest.java b/core/src/test/java/org/apache/metamodel/schema/ColumnTypeTest.java
new file mode 100644
index 0000000..54b0689
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/ColumnTypeTest.java
@@ -0,0 +1,92 @@
+/**
+ * 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.eobjects.metamodel.schema;
+
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import junit.framework.TestCase;
+
+public class ColumnTypeTest extends TestCase {
+
+	public void testConvertColumnTypeFromJdbcTypes() throws Exception {
+		ColumnType type = ColumnType.convertColumnType(Types.VARCHAR);
+		assertEquals(ColumnType.VARCHAR, type);
+		
+		type = ColumnType.convertColumnType(Types.DATE);
+        assertEquals(ColumnType.DATE, type);
+
+		type = ColumnType.convertColumnType(Types.TIME);
+		assertEquals(ColumnType.TIME, type);
+
+		type = ColumnType.convertColumnType(Types.TIMESTAMP);
+		assertEquals(ColumnType.TIMESTAMP, type);
+
+		type = ColumnType.convertColumnType(42397443);
+		assertEquals(ColumnType.OTHER, type);
+		
+		type = ColumnType.convertColumnType(-42397443);
+		assertEquals(ColumnType.OTHER, type);
+	}
+	
+	public void testConvertColumnTypeFromJavaClass() throws Exception {
+		ColumnType type = ColumnType.convertColumnType(String.class);
+		assertEquals(ColumnType.VARCHAR, type);
+
+		type = ColumnType.convertColumnType(Time.class);
+		assertEquals(ColumnType.TIME, type);
+
+		type = ColumnType.convertColumnType(Timestamp.class);
+		assertEquals(ColumnType.TIMESTAMP, type);
+		
+		type = ColumnType.convertColumnType(java.sql.Date.class);
+		assertEquals(ColumnType.DATE, type);
+
+		type = ColumnType.convertColumnType(Date.class);
+		assertEquals(ColumnType.TIMESTAMP, type);
+		
+		type = ColumnType.convertColumnType(Integer.class);
+		assertEquals(ColumnType.INTEGER, type);
+		
+		type = ColumnType.convertColumnType(Object.class);
+		assertEquals(ColumnType.OTHER, type);
+		
+		type = ColumnType.convertColumnType(Map.class);
+		assertEquals(ColumnType.MAP, type);
+		type = ColumnType.convertColumnType(HashMap.class);
+		assertEquals(ColumnType.MAP, type);
+		type = ColumnType.convertColumnType(TreeMap.class);
+		assertEquals(ColumnType.MAP, type);
+		
+		type = ColumnType.convertColumnType(List.class);
+		assertEquals(ColumnType.LIST, type);
+		type = ColumnType.convertColumnType(ArrayList.class);
+		assertEquals(ColumnType.LIST, type);
+		type = ColumnType.convertColumnType(LinkedList.class);
+		assertEquals(ColumnType.LIST, type);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/DataTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/DataTypeTest.java b/core/src/test/java/org/apache/metamodel/schema/DataTypeTest.java
new file mode 100644
index 0000000..087062d
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/DataTypeTest.java
@@ -0,0 +1,28 @@
+/**
+ * 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.eobjects.metamodel.schema;
+
+import junit.framework.TestCase;
+
+public class DataTypeTest extends TestCase {
+
+	public void testIsLiteral() throws Exception {
+		assertTrue(ColumnType.NCHAR.isLiteral());
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/ImmutableSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/ImmutableSchemaTest.java b/core/src/test/java/org/apache/metamodel/schema/ImmutableSchemaTest.java
new file mode 100644
index 0000000..476af09
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/ImmutableSchemaTest.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.schema;
+
+import org.eobjects.metamodel.MetaModelTestCase;
+
+public class ImmutableSchemaTest extends MetaModelTestCase {
+
+	public void testConstructor() throws Exception {
+		Schema mutableSchema = getExampleSchema();
+		assertTrue(mutableSchema instanceof MutableSchema);
+
+		ImmutableSchema immutableSchema = new ImmutableSchema(mutableSchema);
+		
+		assertEquals(mutableSchema.getRelationshipCount(), immutableSchema.getRelationshipCount());
+		
+		assertEquals(immutableSchema, mutableSchema);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/Java5Types.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/Java5Types.java b/core/src/test/java/org/apache/metamodel/schema/Java5Types.java
new file mode 100644
index 0000000..8f44fa9
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/Java5Types.java
@@ -0,0 +1,246 @@
+/**
+ * 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.eobjects.metamodel.schema;
+
+/**
+ * This is a copy of the content of Java 5.0's java.sql.Types
+ */
+class Java5Types {
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>BIT</code>.
+	 */
+	public final static int BIT = -7;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>TINYINT</code>.
+	 */
+	public final static int TINYINT = -6;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>SMALLINT</code>.
+	 */
+	public final static int SMALLINT = 5;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>INTEGER</code>.
+	 */
+	public final static int INTEGER = 4;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>BIGINT</code>.
+	 */
+	public final static int BIGINT = -5;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>FLOAT</code>.
+	 */
+	public final static int FLOAT = 6;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>REAL</code>.
+	 */
+	public final static int REAL = 7;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>DOUBLE</code>.
+	 */
+	public final static int DOUBLE = 8;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>NUMERIC</code>.
+	 */
+	public final static int NUMERIC = 2;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>DECIMAL</code>.
+	 */
+	public final static int DECIMAL = 3;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>CHAR</code>.
+	 */
+	public final static int CHAR = 1;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>VARCHAR</code>.
+	 */
+	public final static int VARCHAR = 12;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>LONGVARCHAR</code>.
+	 */
+	public final static int LONGVARCHAR = -1;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>DATE</code>.
+	 */
+	public final static int DATE = 91;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>TIME</code>.
+	 */
+	public final static int TIME = 92;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>TIMESTAMP</code>.
+	 */
+	public final static int TIMESTAMP = 93;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>BINARY</code>.
+	 */
+	public final static int BINARY = -2;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>VARBINARY</code>.
+	 */
+	public final static int VARBINARY = -3;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type
+	 * <code>LONGVARBINARY</code>.
+	 */
+	public final static int LONGVARBINARY = -4;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>NULL</code>.
+	 */
+	public final static int NULL = 0;
+
+	/**
+	 * The constant in the Java programming language that indicates that the SQL
+	 * type is database-specific and gets mapped to a Java object that can be
+	 * accessed via the methods <code>getObject</code> and
+	 * <code>setObject</code>.
+	 */
+	public final static int OTHER = 1111;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>JAVA_OBJECT</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int JAVA_OBJECT = 2000;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>DISTINCT</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int DISTINCT = 2001;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>STRUCT</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int STRUCT = 2002;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>ARRAY</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int ARRAY = 2003;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>BLOB</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int BLOB = 2004;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>CLOB</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int CLOB = 2005;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>REF</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int REF = 2006;
+
+	/**
+	 * The constant in the Java programming language, somtimes referred to as a
+	 * type code, that identifies the generic SQL type <code>DATALINK</code>.
+	 * 
+	 * @since 1.4
+	 */
+	public final static int DATALINK = 70;
+
+	/**
+	 * The constant in the Java programming language, somtimes referred to as a
+	 * type code, that identifies the generic SQL type <code>BOOLEAN</code>.
+	 * 
+	 * @since 1.4
+	 */
+	public final static int BOOLEAN = 16;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/Java6Types.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/Java6Types.java b/core/src/test/java/org/apache/metamodel/schema/Java6Types.java
new file mode 100644
index 0000000..d48600a
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/Java6Types.java
@@ -0,0 +1,297 @@
+/**
+ * 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.eobjects.metamodel.schema;
+
+/**
+ * This is a copy of the content of Java 6.0's java.sql.Types
+ */
+class Java6Types {
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>BIT</code>.
+	 */
+	public final static int BIT = -7;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>TINYINT</code>.
+	 */
+	public final static int TINYINT = -6;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>SMALLINT</code>.
+	 */
+	public final static int SMALLINT = 5;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>INTEGER</code>.
+	 */
+	public final static int INTEGER = 4;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>BIGINT</code>.
+	 */
+	public final static int BIGINT = -5;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>FLOAT</code>.
+	 */
+	public final static int FLOAT = 6;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>REAL</code>.
+	 */
+	public final static int REAL = 7;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>DOUBLE</code>.
+	 */
+	public final static int DOUBLE = 8;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>NUMERIC</code>.
+	 */
+	public final static int NUMERIC = 2;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>DECIMAL</code>.
+	 */
+	public final static int DECIMAL = 3;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>CHAR</code>.
+	 */
+	public final static int CHAR = 1;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>VARCHAR</code>.
+	 */
+	public final static int VARCHAR = 12;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>LONGVARCHAR</code>.
+	 */
+	public final static int LONGVARCHAR = -1;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>DATE</code>.
+	 */
+	public final static int DATE = 91;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>TIME</code>.
+	 */
+	public final static int TIME = 92;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>TIMESTAMP</code>.
+	 */
+	public final static int TIMESTAMP = 93;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>BINARY</code>.
+	 */
+	public final static int BINARY = -2;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>VARBINARY</code>.
+	 */
+	public final static int VARBINARY = -3;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type
+	 * <code>LONGVARBINARY</code>.
+	 */
+	public final static int LONGVARBINARY = -4;
+
+	/**
+	 * <P>
+	 * The constant in the Java programming language that identifies the generic
+	 * SQL value <code>NULL</code>.
+	 */
+	public final static int NULL = 0;
+
+	/**
+	 * The constant in the Java programming language that indicates that the SQL
+	 * type is database-specific and gets mapped to a Java object that can be
+	 * accessed via the methods <code>getObject</code> and
+	 * <code>setObject</code>.
+	 */
+	public final static int OTHER = 1111;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>JAVA_OBJECT</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int JAVA_OBJECT = 2000;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>DISTINCT</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int DISTINCT = 2001;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>STRUCT</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int STRUCT = 2002;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>ARRAY</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int ARRAY = 2003;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>BLOB</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int BLOB = 2004;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>CLOB</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int CLOB = 2005;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>REF</code>.
+	 * 
+	 * @since 1.2
+	 */
+	public final static int REF = 2006;
+
+	/**
+	 * The constant in the Java programming language, somtimes referred to as a
+	 * type code, that identifies the generic SQL type <code>DATALINK</code>.
+	 * 
+	 * @since 1.4
+	 */
+	public final static int DATALINK = 70;
+
+	/**
+	 * The constant in the Java programming language, somtimes referred to as a
+	 * type code, that identifies the generic SQL type <code>BOOLEAN</code>.
+	 * 
+	 * @since 1.4
+	 */
+	public final static int BOOLEAN = 16;
+
+	// ------------------------- JDBC 4.0 -----------------------------------
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>ROWID</code>
+	 * 
+	 * @since 1.6
+	 * 
+	 */
+	public final static int ROWID = -8;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>NCHAR</code>
+	 * 
+	 * @since 1.6
+	 */
+	public static final int NCHAR = -15;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>NVARCHAR</code>.
+	 * 
+	 * @since 1.6
+	 */
+	public static final int NVARCHAR = -9;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>LONGNVARCHAR</code>.
+	 * 
+	 * @since 1.6
+	 */
+	public static final int LONGNVARCHAR = -16;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>NCLOB</code>.
+	 * 
+	 * @since 1.6
+	 */
+	public static final int NCLOB = 2011;
+
+	/**
+	 * The constant in the Java programming language, sometimes referred to as a
+	 * type code, that identifies the generic SQL type <code>XML</code>.
+	 * 
+	 * @since 1.6
+	 */
+	public static final int SQLXML = 2009;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/JavaTypesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/JavaTypesTest.java b/core/src/test/java/org/apache/metamodel/schema/JavaTypesTest.java
new file mode 100644
index 0000000..2d5eb9c
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/JavaTypesTest.java
@@ -0,0 +1,50 @@
+/**
+ * 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.eobjects.metamodel.schema;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import junit.framework.TestCase;
+
+public class JavaTypesTest extends TestCase {
+
+	/**
+	 * Tests that the constant values of java 6 is backwards compatible with
+	 * java 5
+	 */
+	public void testConstantValues() throws Exception {
+		Class<Java5Types> types5 = Java5Types.class;
+		Class<JdbcTypes> types6 = JdbcTypes.class;
+		Field[] fields = types5.getFields();
+		for (int i = 0; i < fields.length; i++) {
+			Field field5 = fields[i];
+			String fieldName = field5.getName();
+			int mod = field5.getModifiers();
+			if (Modifier.isFinal(mod) && Modifier.isPublic(mod)
+					&& Modifier.isStatic(mod)) {
+				int value5 = field5.getInt(null);
+				Field field6 = types6.getField(fieldName);
+				int value6 = field6.getInt(null);
+				assertEquals("Value of field " + fieldName
+						+ " was not the same", value5, value6);
+			}
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/MutableColumnTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/MutableColumnTest.java b/core/src/test/java/org/apache/metamodel/schema/MutableColumnTest.java
new file mode 100644
index 0000000..a2b3ca6
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/MutableColumnTest.java
@@ -0,0 +1,66 @@
+/**
+ * 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.eobjects.metamodel.schema;
+
+import junit.framework.TestCase;
+
+public class MutableColumnTest extends TestCase {
+
+	/**
+	 * Tests that the following (general) rules apply to the object:
+	 * 
+	 * <li>the hashcode is the same when run twice on an unaltered object</li>
+	 * <li>if o1.equals(o2) then this condition must be true: o1.hashCode() ==
+	 * 02.hashCode()
+	 */
+	public void testEqualsAndHashCode() throws Exception {
+		Column column1 = new MutableColumn("foo");
+		Column column2 = new MutableColumn("foo");
+
+		assertEquals(column1.hashCode(), column2.hashCode());
+		assertEquals(column1, column2);
+
+		column2 = new MutableColumn("bar");
+		assertFalse(column1.equals(column2));
+
+		column2 = new MutableColumn("foo", ColumnType.VARBINARY);
+		assertFalse(column1.equals(column2));
+
+		column1 = new MutableColumn("foo", ColumnType.VARBINARY);
+		assertTrue(column1.equals(column2));
+	}
+
+	public void testQualifiedLabel() throws Exception {
+		MutableSchema s = new MutableSchema("FOO_SCHEMA");
+		MutableTable t = new MutableTable("FOO_TABLE");
+		MutableColumn c = new MutableColumn("FOO_COLUMN");
+
+		assertEquals("FOO_COLUMN", c.getQualifiedLabel());
+		t.addColumn(c);
+		c.setTable(t);
+		assertEquals("FOO_TABLE.FOO_COLUMN", c.getQualifiedLabel());
+		s.addTable(t);
+		t.setSchema(s);
+		assertEquals("FOO_SCHEMA.FOO_TABLE.FOO_COLUMN", c.getQualifiedLabel());
+
+		s.setName("new_schema_name");
+		assertEquals("new_schema_name.FOO_TABLE.FOO_COLUMN",
+				c.getQualifiedLabel());
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/MutableSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/MutableSchemaTest.java b/core/src/test/java/org/apache/metamodel/schema/MutableSchemaTest.java
new file mode 100644
index 0000000..8eca7b2
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/MutableSchemaTest.java
@@ -0,0 +1,61 @@
+/**
+ * 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.eobjects.metamodel.schema;
+
+import junit.framework.TestCase;
+
+public class MutableSchemaTest extends TestCase {
+
+    /**
+     * Tests that the following (general) rules apply to the object:
+     * 
+     * <li>the hashcode is the same when run twice on an unaltered object</li>
+     * <li>if o1.equals(o2) then this condition must be true: o1.hashCode() ==
+     * 02.hashCode()
+     */
+    public void testEqualsAndHashCode() throws Exception {
+        MutableSchema schema1 = new MutableSchema("foo");
+        MutableSchema schema2 = new MutableSchema("foo");
+
+        assertTrue(schema1.equals(schema2));
+        assertTrue(schema1.hashCode() == schema2.hashCode());
+
+        schema2.addTable(new MutableTable("foo"));
+        assertFalse(schema1.equals(schema2));
+        assertTrue(schema1.hashCode() == schema2.hashCode());
+
+        schema2 = new MutableSchema("foo");
+        assertTrue(schema1.equals(schema2));
+        assertTrue(schema1.hashCode() == schema2.hashCode());
+    }
+
+    public void testGetTableByName() throws Exception {
+        MutableSchema s = new MutableSchema("foobar");
+        s.addTable(new MutableTable("Foo"));
+        s.addTable(new MutableTable("FOO"));
+        s.addTable(new MutableTable("bar"));
+
+        assertEquals("Foo", s.getTableByName("Foo").getName());
+        assertEquals("FOO", s.getTableByName("FOO").getName());
+        assertEquals("bar", s.getTableByName("bar").getName());
+
+        // picking the first alternative that matches case insensitively
+        assertEquals("Foo", s.getTableByName("fOO").getName());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/MutableTableTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/MutableTableTest.java b/core/src/test/java/org/apache/metamodel/schema/MutableTableTest.java
new file mode 100644
index 0000000..4efb0d6
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/MutableTableTest.java
@@ -0,0 +1,96 @@
+/**
+ * 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.eobjects.metamodel.schema;
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+public class MutableTableTest extends TestCase {
+
+    /**
+     * Tests that the following (general) rules apply to the object:
+     * 
+     * <li>the hashcode is the same when run twice on an unaltered object</li>
+     * <li>if o1.equals(o2) then this condition must be true: o1.hashCode() ==
+     * 02.hashCode()
+     */
+    public void testEqualsAndHashCode() throws Exception {
+        MutableTable table1 = new MutableTable("Foo").addColumn(new MutableColumn("col1"));
+        MutableTable table2 = new MutableTable("Foo").addColumn(new MutableColumn("col1"));
+
+        assertFalse(table2.equals(null));
+        assertEquals(table1.hashCode(), table2.hashCode());
+        assertEquals(table1, table2);
+
+        table2.addColumn(new MutableColumn("bar"));
+        assertFalse(table1.equals(table2));
+
+        int table1hash = table1.hashCode();
+        int table2hash = table2.hashCode();
+        assertTrue(table1hash + "==" + table2hash, table1hash == table2hash);
+    }
+
+    public void testGetColumnsOfType() throws Exception {
+        MutableTable t = new MutableTable("foo");
+        t.addColumn(new MutableColumn("b").setType(ColumnType.VARCHAR));
+        t.addColumn(new MutableColumn("a").setType(ColumnType.VARCHAR));
+        t.addColumn(new MutableColumn("r").setType(ColumnType.INTEGER));
+
+        Column[] cols = t.getColumnsOfType(ColumnType.VARCHAR);
+        assertEquals(2, cols.length);
+        assertEquals("b", cols[0].getName());
+        assertEquals("a", cols[1].getName());
+
+        cols = t.getColumnsOfType(ColumnType.INTEGER);
+        assertEquals(1, cols.length);
+        assertEquals("r", cols[0].getName());
+
+        cols = t.getColumnsOfType(ColumnType.FLOAT);
+        assertEquals(0, cols.length);
+    }
+
+    public void testGetIndexedColumns() throws Exception {
+        MutableTable t = new MutableTable("foo");
+        t.addColumn(new MutableColumn("b").setIndexed(true));
+        t.addColumn(new MutableColumn("a").setIndexed(false));
+        t.addColumn(new MutableColumn("r").setIndexed(true));
+        Column[] indexedColumns = t.getIndexedColumns();
+        assertEquals(
+                "[Column[name=b,columnNumber=0,type=null,nullable=null,nativeType=null,columnSize=null], Column[name=r,columnNumber=0,type=null,nullable=null,nativeType=null,columnSize=null]]",
+                Arrays.toString(indexedColumns));
+        for (Column column : indexedColumns) {
+            assertTrue(column.isIndexed());
+        }
+    }
+
+    public void testGetColumnByName() throws Exception {
+        MutableTable t = new MutableTable("foobar");
+        t.addColumn(new MutableColumn("Foo"));
+        t.addColumn(new MutableColumn("FOO"));
+        t.addColumn(new MutableColumn("bar"));
+
+        assertEquals("Foo", t.getColumnByName("Foo").getName());
+        assertEquals("FOO", t.getColumnByName("FOO").getName());
+        assertEquals("bar", t.getColumnByName("bar").getName());
+
+        // picking the first alternative that matches case insensitively
+        assertEquals("Foo", t.getColumnByName("fOO").getName());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/SchemaModelTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/SchemaModelTest.java b/core/src/test/java/org/apache/metamodel/schema/SchemaModelTest.java
new file mode 100644
index 0000000..380d9d1
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/SchemaModelTest.java
@@ -0,0 +1,104 @@
+/**
+ * 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.eobjects.metamodel.schema;
+
+import java.util.Arrays;
+
+import org.eobjects.metamodel.MetaModelTestCase;
+
+public class SchemaModelTest extends MetaModelTestCase {
+
+    public void testGetExampleSchema() throws Exception {
+        Schema schema = getExampleSchema();
+        assertEquals("MetaModelSchema", schema.getName());
+        assertEquals("Schema[name=MetaModelSchema]", schema.toString());
+        assertEquals(5, schema.getRelationships().length);
+
+        assertEquals(4, schema.getTableCount());
+        assertEquals(3, schema.getTableCount(TableType.TABLE));
+        assertEquals(1, schema.getTableCount(TableType.VIEW));
+
+        assertNull(schema.getTableByName("foobar"));
+        assertNull(schema.getTableByName(null));
+
+        Table contributorTable = schema.getTableByName(TABLE_CONTRIBUTOR);
+        assertEquals(3, contributorTable.getColumnCount());
+        assertEquals(2, contributorTable.getRelationshipCount());
+
+        Table projectTable = schema.getTableByName(TABLE_PROJECT);
+        assertEquals(4, projectTable.getColumnCount());
+        assertEquals(2, projectTable.getRelationshipCount());
+        assertNotNull(projectTable.getColumnByName("project_id"));
+
+        assertEquals("[project_id, name, lines_of_code, parent_project_id]",
+                Arrays.toString(projectTable.getColumnNames()));
+
+        assertEquals(
+                "[Column[name=project_id,columnNumber=0,type=INTEGER,nullable=false,nativeType=null,columnSize=null], "
+                        + "Column[name=lines_of_code,columnNumber=2,type=BIGINT,nullable=true,nativeType=null,columnSize=null], "
+                        + "Column[name=parent_project_id,columnNumber=3,type=INTEGER,nullable=true,nativeType=null,columnSize=null]]",
+                Arrays.toString(projectTable.getNumberColumns()));
+
+        assertEquals("[Column[name=name,columnNumber=1,type=VARCHAR,nullable=false,nativeType=null,columnSize=null]]",
+                Arrays.toString(projectTable.getLiteralColumns()));
+
+        assertEquals("[]", Arrays.toString(projectTable.getTimeBasedColumns()));
+
+        assertNull(projectTable.getColumnByName("foobar"));
+        assertNull(projectTable.getColumnByName(null));
+
+        Table roleTable = schema.getTableByName(TABLE_ROLE);
+        assertEquals(3, roleTable.getColumnCount());
+        assertEquals(3, roleTable.getRelationshipCount());
+
+        Table projectContributorView = schema.getTableByName(TABLE_PROJECT_CONTRIBUTOR);
+        assertEquals(3, projectContributorView.getColumnCount());
+        assertEquals(3, projectContributorView.getRelationshipCount());
+
+        Relationship[] projectContributorToContributorRelations = projectContributorView
+                .getRelationships(contributorTable);
+        assertEquals(1, projectContributorToContributorRelations.length);
+        Relationship[] contributorToProjectContributorRelations = contributorTable
+                .getRelationships(projectContributorView);
+        assertEquals(1, contributorToProjectContributorRelations.length);
+        assertTrue(Arrays.equals(projectContributorToContributorRelations, contributorToProjectContributorRelations));
+
+        assertEquals(
+                "Relationship[primaryTable=contributor,primaryColumns=[name],foreignTable=project_contributor,foreignColumns=[contributor]]",
+                projectContributorToContributorRelations[0].toString());
+
+        ((MutableRelationship) projectContributorToContributorRelations[0]).remove();
+        projectContributorToContributorRelations = projectContributorView.getRelationships(contributorTable);
+        assertEquals(0, projectContributorToContributorRelations.length);
+        contributorToProjectContributorRelations = contributorTable.getRelationships(projectContributorView);
+        assertEquals(0, contributorToProjectContributorRelations.length);
+
+        // Get primary keys / Get foreign keys test
+        assertEquals(
+                "[Column[name=contributor_id,columnNumber=0,type=INTEGER,nullable=false,nativeType=null,columnSize=null]]",
+                Arrays.toString(contributorTable.getPrimaryKeys()));
+        assertEquals("[]", Arrays.toString(contributorTable.getForeignKeys()));
+
+        assertEquals(
+                "[Column[name=contributor_id,columnNumber=0,type=INTEGER,nullable=false,nativeType=null,columnSize=null], Column[name=project_id,columnNumber=1,type=INTEGER,nullable=false,nativeType=null,columnSize=null]]",
+                Arrays.toString(roleTable.getPrimaryKeys()));
+        Column[] foreignKeys = roleTable.getForeignKeys();
+        assertEquals(2, foreignKeys.length);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/schema/TableTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/schema/TableTypeTest.java b/core/src/test/java/org/apache/metamodel/schema/TableTypeTest.java
new file mode 100644
index 0000000..127c54b
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/schema/TableTypeTest.java
@@ -0,0 +1,38 @@
+/**
+ * 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.eobjects.metamodel.schema;
+
+import junit.framework.TestCase;
+
+public class TableTypeTest extends TestCase {
+
+	public void testGetTableType() throws Exception {
+		assertSame(TableType.TABLE, TableType.getTableType("table"));
+		assertSame(TableType.VIEW, TableType.getTableType("view"));
+		assertSame(TableType.GLOBAL_TEMPORARY, TableType
+				.getTableType("GLOBAL_TEMPORARY"));
+		assertSame(TableType.SYSTEM_TABLE, TableType
+				.getTableType("system_table"));
+		assertSame(TableType.LOCAL_TEMPORARY, TableType
+				.getTableType("LOCAL_TEMPORARY"));
+		assertSame(TableType.ALIAS, TableType.getTableType("alIAs"));
+		assertSame(TableType.SYNONYM, TableType.getTableType("synonym"));
+		assertSame(TableType.OTHER, TableType.getTableType("foobar"));
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/util/AlphabeticSequenceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/util/AlphabeticSequenceTest.java b/core/src/test/java/org/apache/metamodel/util/AlphabeticSequenceTest.java
new file mode 100644
index 0000000..075098e
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/util/AlphabeticSequenceTest.java
@@ -0,0 +1,69 @@
+/**
+ * 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.eobjects.metamodel.util;
+
+import junit.framework.TestCase;
+
+public class AlphabeticSequenceTest extends TestCase {
+	
+	public void testNoArgsConstructor() throws Exception {
+		AlphabeticSequence seq = new AlphabeticSequence();
+		assertEquals("A", seq.next());
+	}
+
+	public void testNext() throws Exception {
+		AlphabeticSequence seq = new AlphabeticSequence("A");
+		assertEquals("A", seq.current());
+		assertEquals("B", seq.next());
+		assertEquals("C", seq.next());
+		assertEquals("D", seq.next());
+		assertEquals("E", seq.next());
+		assertEquals("F", seq.next());
+		assertEquals("G", seq.next());
+		assertEquals("H", seq.next());
+		assertEquals("I", seq.next());
+		assertEquals("J", seq.next());
+		assertEquals("K", seq.next());
+		assertEquals("L", seq.next());
+		assertEquals("M", seq.next());
+		assertEquals("N", seq.next());
+		assertEquals("O", seq.next());
+		assertEquals("P", seq.next());
+		assertEquals("Q", seq.next());
+		assertEquals("R", seq.next());
+		assertEquals("S", seq.next());
+		assertEquals("T", seq.next());
+		assertEquals("U", seq.next());
+		assertEquals("V", seq.next());
+		assertEquals("W", seq.next());
+		assertEquals("X", seq.next());
+		assertEquals("Y", seq.next());
+		assertEquals("Z", seq.next());
+		assertEquals("AA", seq.next());
+		
+		seq = new AlphabeticSequence("AZ");
+		assertEquals("BA", seq.next());
+		
+		seq = new AlphabeticSequence("ZZ");
+		assertEquals("AAA", seq.next());
+		
+		seq = new AlphabeticSequence("ABZ");
+		assertEquals("ACA", seq.next());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/test/java/org/apache/metamodel/util/BaseObjectTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/util/BaseObjectTest.java b/core/src/test/java/org/apache/metamodel/util/BaseObjectTest.java
new file mode 100644
index 0000000..e147bc1
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/util/BaseObjectTest.java
@@ -0,0 +1,49 @@
+/**
+ * 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.eobjects.metamodel.util;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public class BaseObjectTest extends TestCase {
+
+	class MyClass extends BaseObject {
+		private int[] ints;
+
+		@Override
+		protected void decorateIdentity(List<Object> identifiers) {
+			identifiers.add(ints);
+		}
+	}
+
+	public void testHashCodeForPrimitiveArray() throws Exception {
+		MyClass o1 = new MyClass();
+		o1.ints = new int[] { 1, 2, 3 };
+		MyClass o2 = new MyClass();
+		o2.ints = new int[] { 4, 5, 6 };
+		MyClass o3 = new MyClass();
+		o3.ints = new int[] { 1, 2, 3 };
+
+		assertTrue(o1.hashCode() == o1.hashCode());
+		assertTrue(o1.hashCode() == o3.hashCode());
+		assertFalse(o1.hashCode() == o2.hashCode());
+		assertFalse(o3.hashCode() == o2.hashCode());
+	}
+}