From 6ea31ce77969df430e8184b6e8ab54f32c212a71 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Fri, 15 Oct 2010 13:56:33 -0500 Subject: [PATCH] HHH-5662 - Import the initial work --- .../relational/AbstractConstraint.java | 6 +- .../AbstractTableSpecification.java | 16 +++ .../relational/AbstractValueContainer.java | 2 +- .../metamodel/relational/Column.java | 32 +++-- .../metamodel/relational/Constraint.java | 2 +- .../metamodel/relational/ForeignKey.java | 23 +++- .../hibernate/metamodel/relational/Index.java | 2 +- .../metamodel/relational/PrimaryKey.java | 4 +- .../hibernate/metamodel/relational/Table.java | 25 +++- .../relational/TableSpecification.java | 8 +- .../metamodel/relational/UniqueKey.java | 2 +- .../metamodel/relational/ValueContainer.java | 2 +- .../metamodel/relational/ObjectNameTests.java | 61 ++++++++++ .../relational/TableManipulationTests.java | 111 ++++++++++++++++++ 14 files changed, 271 insertions(+), 25 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/relational/ObjectNameTests.java create mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java index 74140a6ff3..2075a44eea 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractConstraint.java @@ -51,7 +51,11 @@ public abstract class AbstractConstraint implements Constraint { return name; } - public List getColumns() { + public Iterable getColumns() { + return columns; + } + + protected List internalColumnAccess() { return columns; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java index 08a13acfca..8f80eee3dc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java @@ -23,6 +23,9 @@ */ package org.hibernate.metamodel.relational; +import java.util.ArrayList; +import java.util.List; + /** * Convenience base class for implementing the {@link ValueContainer} contract centralizing commonality * between modelling tables views and inline views. @@ -31,6 +34,19 @@ package org.hibernate.metamodel.relational; */ public abstract class AbstractTableSpecification extends AbstractValueContainer implements TableSpecification { private PrimaryKey primaryKey = new PrimaryKey( this ); + private List foreignKeys = new ArrayList(); + + @Override + public Iterable getForeignKeys() { + return foreignKeys; + } + + @Override + public ForeignKey createForeignKey(TableSpecification targetTable, String name) { + ForeignKey fk = new ForeignKey( this, targetTable, name ); + foreignKeys.add( fk ); + return fk; + } /** * {@inheritDoc} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractValueContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractValueContainer.java index c679185518..c183b64fdf 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractValueContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractValueContainer.java @@ -34,7 +34,7 @@ public abstract class AbstractValueContainer implements ValueContainer { private final LinkedHashSet values = new LinkedHashSet(); @Override - public Iterable iterateValues() { + public Iterable values() { return values; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java index e9f30ed78a..13218533bf 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java @@ -85,20 +85,36 @@ public class Column extends AbstractSimpleValue implements SimpleValue { this.lobMultiplier = lobMultiplier; } - public Size(int precision) { - this( precision, -1, -1, null ); + public static Size precision(int precision) { + return new Size( precision, -1, -1, null ); } - public Size(int precision, int scale) { - this( precision, scale, -1, null ); + public static Size precision(int precision, int scale) { + return new Size( precision, scale, -1, null ); } - public Size(long length) { - this( -1, -1, length, null ); + public static Size length(long length) { + return new Size( -1, -1, length, null ); } - public Size(long length, LobMultiplier lobMultiplier) { - this( -1, -1, length, lobMultiplier ); + public static Size length(long length, LobMultiplier lobMultiplier) { + return new Size( -1, -1, length, lobMultiplier ); + } + + public int getPrecision() { + return precision; + } + + public int getScale() { + return scale; + } + + public long getLength() { + return length; + } + + public LobMultiplier getLobMultiplier() { + return lobMultiplier; } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Constraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Constraint.java index 3dec833664..c1348eeed1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Constraint.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Constraint.java @@ -54,5 +54,5 @@ public interface Constraint { * * @return The constrained columns. */ - public List getColumns(); + public Iterable getColumns(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ForeignKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ForeignKey.java index d8f9ac97ca..a7a05b349f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ForeignKey.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ForeignKey.java @@ -44,12 +44,12 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export private final TableSpecification targetTable; private List targetColumns; - public ForeignKey(TableSpecification sourceTable, TableSpecification targetTable, String name) { + protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable, String name) { super( sourceTable, name ); this.targetTable = targetTable; } - public ForeignKey(TableSpecification sourceTable, TableSpecification targetTable) { + protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable) { this( sourceTable, targetTable, null ); } @@ -61,16 +61,21 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export return targetTable; } - public List getSourceColumns() { + public Iterable getSourceColumns() { return getColumns(); } - public List getTargetColumns() { + public Iterable getTargetColumns() { return targetColumns == null ? getTargetTable().getPrimaryKey().getColumns() : targetColumns; } + @Override + public void addColumn(Column column) { + addColumnMapping( column, null ); + } + public void addColumnMapping(Column sourceColumn, Column targetColumn) { if ( targetColumn == null ) { if ( targetColumns != null ) { @@ -85,7 +90,7 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export } else { if ( targetColumns == null ) { - if ( !getSourceColumns().isEmpty() ) { + if ( !internalColumnAccess().isEmpty() ) { log.warn( "Value mapping mismatch as part of FK [table=" + getTable().toLoggableString() + ", name=" + getName() + "] while adding source column [" @@ -96,11 +101,17 @@ public class ForeignKey extends AbstractConstraint implements Constraint, Export } targetColumns.add( targetColumn ); } - getSourceColumns().add( sourceColumn ); + internalColumnAccess().add( sourceColumn ); } @Override public String getExportIdentifier() { return getSourceTable().getLoggableValueQualifier() + ".FK-" + getName(); } + + public void validate() { + if ( getSourceTable() == null ) { + + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Index.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Index.java index 74694bdf66..089dc737f2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Index.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Index.java @@ -30,7 +30,7 @@ package org.hibernate.metamodel.relational; * @author Steve Ebersole */ public class Index extends AbstractConstraint implements Constraint { - protected Index(TableSpecification table, String name) { + protected Index(Table table, String name) { super( table, name ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/PrimaryKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/PrimaryKey.java index f92b121bb4..f21be3a344 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/PrimaryKey.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/PrimaryKey.java @@ -37,9 +37,11 @@ public class PrimaryKey extends AbstractConstraint implements Constraint, Export // (1) primary keys are not required to be named. // (2) because a primary key is required for each table, it is easier to allow setting the constraint name // later in terms of building the metamodel + // + // todo : default name? {TABLE_NAME}_PK maybe? private String name; - public PrimaryKey(TableSpecification table) { + protected PrimaryKey(TableSpecification table) { super( table, null ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java index f68608482e..0ffa1a6c79 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java @@ -23,6 +23,8 @@ */ package org.hibernate.metamodel.relational; +import java.util.ArrayList; +import java.util.List; import java.util.Set; /** @@ -35,6 +37,9 @@ public class Table extends AbstractTableSpecification implements ValueContainer, private final ObjectName name; private final Set spaces; + private List indexes; + private List uniqueKeys; + public Table(ObjectName name) { this.name = name; this.spaces = java.util.Collections.singleton( name ); @@ -55,7 +60,7 @@ public class Table extends AbstractTableSpecification implements ValueContainer, } @Override - public Set getSpaces() { + public Iterable getSpaces() { return spaces; } @@ -64,6 +69,24 @@ public class Table extends AbstractTableSpecification implements ValueContainer, return getObjectName().getIdentifier(); } + public Index createIndex(String name) { + Index index = new Index( this, name ); + if ( indexes == null ) { + indexes = new ArrayList(); + } + indexes.add( index ); + return index; + } + + public UniqueKey createUniqueKey(String name) { + UniqueKey uniqueKey = new UniqueKey( this, name ); + if ( uniqueKeys == null ) { + uniqueKeys = new ArrayList(); + } + uniqueKeys.add( uniqueKey ); + return uniqueKey; + } + @Override public String toString() { return "Table{" + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java index f63702ec3b..f28ce7d3d3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java @@ -23,8 +23,6 @@ */ package org.hibernate.metamodel.relational; -import java.util.Set; - /** * Models what ANSI SQL terms a table specification which is a table or a view or an inline view. * @@ -38,10 +36,14 @@ public interface TableSpecification extends ValueContainer { */ public PrimaryKey getPrimaryKey(); + public ForeignKey createForeignKey(TableSpecification targetTable, String name); + + public Iterable getForeignKeys(); + /** * Get the physical table names modelled here. This is especially important in the case of an inline view. * * @return The spaces. */ - public Set getSpaces(); + public Iterable getSpaces(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java index 5ed1a35386..fb1c9d85b4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java @@ -30,7 +30,7 @@ package org.hibernate.metamodel.relational; * @author Steve Ebersole */ public class UniqueKey extends AbstractConstraint implements Constraint { - protected UniqueKey(TableSpecification table, String name) { + protected UniqueKey(Table table, String name) { super( table, name ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ValueContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ValueContainer.java index c0387bc728..98a88cc59d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ValueContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/ValueContainer.java @@ -36,7 +36,7 @@ public interface ValueContainer { * * @return Iterator over value definitions. */ - public Iterable iterateValues(); + public Iterable values(); /** * Get a qualifier which can be used to qualify {@link Value values} belonging to this container in diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/relational/ObjectNameTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/relational/ObjectNameTests.java new file mode 100644 index 0000000000..6e3342d050 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/relational/ObjectNameTests.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.relational; + +import org.hibernate.testing.junit.UnitTestCase; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class ObjectNameTests extends UnitTestCase { + public ObjectNameTests(String string) { + super( string ); + } + + public void testMissingName() { + try { + new ObjectName( (String)null, null, null ); + fail(); + } + catch ( IllegalIdentifierException ignore ) { + } + + try { + new ObjectName( "schema", "catalog", null ); + fail(); + } + catch ( IllegalIdentifierException ignore ) { + } + } + + public void testIdentifierBuilding() { + ObjectName on = new ObjectName( "schema", "catalog", "name" ); + assertEquals( "schema.catalog.name", on.getIdentifier() ); + on = new ObjectName( "schema", null, "name" ); + assertEquals( "schema.name", on.getIdentifier() ); + } +} + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java new file mode 100644 index 0000000000..b8e292ed77 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java @@ -0,0 +1,111 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.relational; + +import java.sql.Types; + +import org.hibernate.testing.junit.UnitTestCase; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class TableManipulationTests extends UnitTestCase { + public static final Datatype VARCHAR = new Datatype( Types.VARCHAR, "VARCHAR", String.class ); + public static final Datatype INTEGER = new Datatype( Types.INTEGER, "INTEGER", Long.class ); + + public TableManipulationTests(String string) { + super( string ); + } + + public void testTableCreation() { + Table table = new Table( new ObjectName( null, null, "my_table" ) ); + assertNull( table.getObjectName().getSchema() ); + assertNull( table.getObjectName().getCatalog() ); + assertEquals( "my_table", table.getObjectName().getName().toString() ); + assertEquals( "my_table", table.getExportIdentifier() ); + assertNull( table.getPrimaryKey().getName() ); + assertFalse( table.values().iterator().hasNext() ); + + Column idColumn = table.createColumn( "id" ); + idColumn.setDatatype( INTEGER ); + idColumn.setSize( Column.Size.precision( 18, 0 ) ); + table.getPrimaryKey().addColumn( idColumn ); + table.getPrimaryKey().setName( "my_table_pk" ); + assertEquals( "my_table_pk", table.getPrimaryKey().getName() ); + assertEquals( "my_table.PK", table.getPrimaryKey().getExportIdentifier() ); + + Column col_1 = table.createColumn( "col_1" ); + col_1.setDatatype( VARCHAR ); + col_1.setSize( Column.Size.length( 512 ) ); + + for ( Value value : table.values() ) { + assertTrue( Column.class.isInstance( value ) ); + Column column = ( Column ) value; + if ( column.getName().equals( "id" ) ) { + assertEquals( INTEGER, column.getDatatype() ); + assertEquals( 18, column.getSize().getPrecision() ); + assertEquals( 0, column.getSize().getScale() ); + assertEquals( -1, column.getSize().getLength() ); + assertNull( column.getSize().getLobMultiplier() ); + } + else { + assertEquals( "col_1", column.getName() ); + assertEquals( VARCHAR, column.getDatatype() ); + assertEquals( -1, column.getSize().getPrecision() ); + assertEquals( -1, column.getSize().getScale() ); + assertEquals( 512, column.getSize().getLength() ); + assertNull( column.getSize().getLobMultiplier() ); + } + } + } + + public void testBasicForeignKeyDefinition() { + Table book = new Table( new ObjectName( null, null, "BOOK" ) ); + + Column bookId = book.createColumn( "id" ); + bookId.setDatatype( INTEGER ); + bookId.setSize( Column.Size.precision( 18, 0 ) ); + book.getPrimaryKey().addColumn( bookId ); + book.getPrimaryKey().setName( "BOOK_PK" ); + + Table page = new Table( new ObjectName( null, null, "PAGE" ) ); + + Column pageId = page.createColumn( "id" ); + pageId.setDatatype( INTEGER ); + pageId.setSize( Column.Size.precision( 18, 0 ) ); + page.getPrimaryKey().addColumn( pageId ); + page.getPrimaryKey().setName( "PAGE_PK" ); + + Column pageBookId = page.createColumn( "BOOK_ID" ); + pageId.setDatatype( INTEGER ); + pageId.setSize( Column.Size.precision( 18, 0 ) ); + ForeignKey pageBookFk = page.createForeignKey( book, "PAGE_BOOK_FK" ); + pageBookFk.addColumn( pageBookId ); + + assertEquals( page, pageBookFk.getSourceTable() ); + assertEquals( book, pageBookFk.getTargetTable() ); + } +}