Skip to content

Commit 46a34a4

Browse files
HHH-7612 - Fix and test
1 parent b77d5ae commit 46a34a4

File tree

7 files changed

+199
-10
lines changed

7 files changed

+199
-10
lines changed

hibernate-core/src/main/java/org/hibernate/mapping/Table.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.HashMap;
3030
import java.util.Iterator;
3131
import java.util.LinkedHashMap;
32+
import java.util.LinkedHashSet;
3233
import java.util.List;
3334
import java.util.Map;
3435

@@ -457,7 +458,7 @@ public String sqlTemporaryTableCreateString(Dialect dialect, Mapping mapping) th
457458
.append( ' ' )
458459
.append( name )
459460
.append( " (" );
460-
Iterator itr = getColumnIterator();
461+
Iterator itr = getSortedColumnIterator();
461462
while ( itr.hasNext() ) {
462463
final Column column = (Column) itr.next();
463464
buffer.append( column.getQuotedName( dialect ) ).append( ' ' );
@@ -491,7 +492,7 @@ public String sqlCreateString(Dialect dialect, Mapping p, String defaultCatalog,
491492
pkname = ( (Column) getPrimaryKey().getColumnIterator().next() ).getQuotedName( dialect );
492493
}
493494

494-
Iterator iter = getColumnIterator();
495+
Iterator iter = getSortedColumnIterator();
495496
while ( iter.hasNext() ) {
496497
Column col = (Column) iter.next();
497498

@@ -591,6 +592,33 @@ public String sqlCreateString(Dialect dialect, Mapping p, String defaultCatalog,
591592
return buf.append( dialect.getTableTypeString() ).toString();
592593
}
593594

595+
/**
596+
* @return Sorted column list so that primary key appears first, followed by foreign keys and other properties.
597+
* Within each group columns are not sorted in any way.
598+
*/
599+
private Iterator<Column> getSortedColumnIterator() {
600+
final LinkedHashSet<Column> sortedColumns = new LinkedHashSet<Column>();
601+
// Adding primary key columns.
602+
if ( hasPrimaryKey() ) {
603+
sortedColumns.addAll( getPrimaryKey().getColumns() );
604+
}
605+
// Adding foreign key columns.
606+
Iterator iter = getForeignKeyIterator();
607+
while ( iter.hasNext() ) {
608+
ForeignKey fk = (ForeignKey) iter.next();
609+
sortedColumns.addAll( fk.getColumns() );
610+
}
611+
// Adding other columns.
612+
iter = getColumnIterator();
613+
while ( iter.hasNext() ) {
614+
final Column column = (Column) iter.next();
615+
if ( ! sortedColumns.contains( column ) ) {
616+
sortedColumns.add( column );
617+
}
618+
}
619+
return sortedColumns.iterator();
620+
}
621+
594622
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
595623
StringBuilder buf = new StringBuilder( "drop table " );
596624
if ( dialect.supportsIfExistsBeforeTableName() ) {

hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.hibernate.dialect.Dialect;
2828
import org.hibernate.dialect.function.SQLFunctionRegistry;
2929
import org.hibernate.internal.util.StringHelper;
30+
import org.hibernate.internal.util.compare.EqualsHelper;
3031
import org.hibernate.sql.Template;
3132

3233
/**
@@ -225,4 +226,26 @@ else if ( columnName.getText().length() > lastLetter + 1 ) {
225226
}
226227
return alias + suffix;
227228
}
229+
230+
@Override
231+
public boolean equals(Object o) {
232+
if ( this == o ) {
233+
return true;
234+
}
235+
if ( ! ( o instanceof Column ) ) {
236+
return false;
237+
}
238+
239+
final Column that = (Column) o;
240+
241+
return EqualsHelper.equals( this.columnName, that.columnName )
242+
&& EqualsHelper.equals( this.getTable(), that.getTable() );
243+
}
244+
245+
@Override
246+
public int hashCode() {
247+
int result = columnName != null ? columnName.hashCode() : 0;
248+
result = 31 * result + ( getTable() != null ? getTable().hashCode() : 0 );
249+
return result;
250+
}
228251
}

hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@
2626
import java.util.ArrayList;
2727
import java.util.Collections;
2828
import java.util.LinkedHashSet;
29+
import java.util.LinkedList;
2930
import java.util.List;
3031
import java.util.Set;
3132

3233
import org.hibernate.dialect.Dialect;
3334
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
35+
import org.hibernate.internal.util.compare.EqualsHelper;
3436
import org.hibernate.tool.schema.extract.spi.ColumnInformation;
3537
import org.hibernate.tool.schema.extract.spi.TableInformation;
3638

@@ -185,6 +187,30 @@ public String toString() {
185187
return "Table{name=" + exportIdentifier + '}';
186188
}
187189

190+
@Override
191+
public boolean equals(Object o) {
192+
if ( this == o ) {
193+
return true;
194+
}
195+
if ( ! ( o instanceof Table ) ) {
196+
return false;
197+
}
198+
199+
final Table that = (Table) o;
200+
201+
return EqualsHelper.equals( this.database, that.database )
202+
&& EqualsHelper.equals( this.logicalName, that.logicalName )
203+
&& EqualsHelper.equals( this.physicalName, that.physicalName );
204+
}
205+
206+
@Override
207+
public int hashCode() {
208+
int result = database != null ? database.hashCode() : 0;
209+
result = 31 * result + ( physicalName != null ? physicalName.hashCode() : 0 );
210+
result = 31 * result + ( logicalName != null ? logicalName.hashCode() : 0 );
211+
return result;
212+
}
213+
188214
public String[] sqlAlterStrings(TableInformation tableInformation, JdbcEnvironment jdbcEnvironment) {
189215
final Dialect dialect = jdbcEnvironment.getDialect();
190216
final String baseAlterCommand = new StringBuilder( "alter table " )
@@ -251,4 +277,28 @@ public String[] sqlAlterStrings(TableInformation tableInformation, JdbcEnvironme
251277

252278
return commands.toArray( new String[ commands.size() ] );
253279
}
280+
281+
/**
282+
* @return Sorted column list so that primary key appears first, followed by foreign keys and other properties.
283+
* Within each group columns are not sorted in any way.
284+
*/
285+
public Iterable<Column> sortedColumns() {
286+
final Set<Column> sortedColumns = new LinkedHashSet<Column>();
287+
// Adding primary key columns.
288+
sortedColumns.addAll( getPrimaryKey().getColumns() );
289+
// Adding foreign key columns.
290+
for ( ForeignKey fk : getForeignKeys() ) {
291+
sortedColumns.addAll( fk.getColumns() );
292+
}
293+
// Adding other columns.
294+
for ( Value value : values() ) {
295+
if ( value instanceof Column ) {
296+
final Column column = (Column) value;
297+
if ( ! sortedColumns.contains( column ) ) {
298+
sortedColumns.add( column );
299+
}
300+
}
301+
}
302+
return sortedColumns;
303+
}
254304
}

hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,13 @@ public String[] getSqlCreateStrings(Table table, JdbcEnvironment jdbcEnvironment
7070
}
7171

7272
boolean isFirst = true;
73-
for ( Value simpleValue : table.values() ) {
74-
if ( ! Column.class.isInstance( simpleValue ) ) {
75-
continue;
76-
}
73+
for ( Column col : table.sortedColumns() ) {
7774
if ( isFirst ) {
7875
isFirst = false;
7976
}
8077
else {
8178
buf.append( ", " );
8279
}
83-
Column col = ( Column ) simpleValue;
8480
String colName = col.getColumnName().getText( dialect );
8581

8682
buf.append( colName ).append( ' ' );

hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/primarykey/NullablePrimaryKeyTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ public void testGeneratedSql() {
3434
for (String s : schema) {
3535
log.debug(s);
3636
}
37-
String expectedMappingTableSql = "create table personAddress (address_id numeric(19,0), " +
38-
"person_id numeric(19,0) not null, primary key (person_id))";
37+
String expectedMappingTableSql = "create table personAddress (person_id numeric(19,0) not null, " +
38+
"address_id numeric(19,0), primary key (person_id))";
3939
Assert.assertEquals( "Wrong SQL", expectedMappingTableSql, schema[2] );
4040
} catch (Exception e) {
4141
Assert.fail(e.getMessage());
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
INSERT INTO `vgras007_v031` VALUES ('ZZZ','00',1);
22

3-
INSERT INTO `vgras029_v031` VALUES (1,'Foo Foo Foo',1), (1,'Bar Bar Bar',2);
3+
INSERT INTO `vgras029_v031` VALUES (1,1,'Foo Foo Foo'), (1,2,'Bar Bar Bar');
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package org.hibernate.test.schemaupdate;
2+
3+
import java.sql.Types;
4+
5+
import org.junit.After;
6+
import org.junit.Assert;
7+
import org.junit.Before;
8+
import org.junit.Test;
9+
10+
import org.hibernate.cfg.Environment;
11+
import org.hibernate.dialect.Dialect;
12+
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
13+
import org.hibernate.metamodel.spi.relational.Column;
14+
import org.hibernate.metamodel.spi.relational.ForeignKey;
15+
import org.hibernate.metamodel.spi.relational.Identifier;
16+
import org.hibernate.metamodel.spi.relational.Schema;
17+
import org.hibernate.metamodel.spi.relational.Table;
18+
import org.hibernate.service.ServiceRegistry;
19+
import org.hibernate.testing.ServiceRegistryBuilder;
20+
import org.hibernate.testing.TestForIssue;
21+
import org.hibernate.testing.junit4.BaseUnitTestCase;
22+
23+
/**
24+
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
25+
*/
26+
public class SchemaGenerationTest extends BaseUnitTestCase {
27+
private ServiceRegistry serviceRegistry;
28+
29+
@Before
30+
public void setUp() {
31+
serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( Environment.getProperties() );
32+
}
33+
34+
@After
35+
public void tearDown() {
36+
if ( serviceRegistry != null ) {
37+
ServiceRegistryBuilder.destroy( serviceRegistry );
38+
}
39+
}
40+
41+
@Test
42+
@TestForIssue(jiraKey = "HHH-7612")
43+
public void testSqlCreatePrimaryAndForeignKeyOrder() {
44+
final Dialect dialect = createDialect( 32 );
45+
final Table table = new Table(
46+
new Schema( null, null ),
47+
Identifier.toIdentifier( "col_order_table" ),
48+
Identifier.toIdentifier( "col_order_table" )
49+
);
50+
addForeignKeyColumn( table, "fk1", "cot_fk1", dialect.getTypeName( Types.INTEGER ) );
51+
addForeignKeyColumn( table, "fk1", "cot_fk2", dialect.getTypeName( Types.VARCHAR, 32, 0, 0 ) );
52+
table.createColumn( "desc1" ).setSqlType( dialect.getTypeName( Types.VARCHAR, 100, 0, 0 ) );
53+
addPrimaryKeyColumn( table, "pk1", "id1", dialect.getTypeName( Types.INTEGER ) );
54+
addPrimaryKeyColumn( table, "pk1", "id2", dialect.getTypeName( Types.VARCHAR, 32, 0, 0 ) );
55+
table.createColumn( "desc2" ).setSqlType( dialect.getTypeName( Types.BLOB ) );
56+
57+
final String[] sqlCreate = dialect.getTableExporter().getSqlCreateStrings( table, serviceRegistry.getService( JdbcEnvironment.class ) );
58+
59+
Assert.assertEquals(
60+
"PK and FK columns should appear first in CREATE TABLE statement.",
61+
"create table col_order_table (id1 integer, id2 varchar(32), cot_fk1 integer, cot_fk2 varchar(32), desc1 varchar(100), desc2 blob, primary key (id1, id2))",
62+
sqlCreate[0]
63+
);
64+
}
65+
66+
private Dialect createDialect(final int maxAliasLength) {
67+
return new Dialect() {
68+
public int getMaxAliasLength() {
69+
return maxAliasLength;
70+
}
71+
};
72+
}
73+
74+
private void addPrimaryKeyColumn(Table table, String name, String colName, String sqlType) {
75+
final Column column = table.createColumn( colName );
76+
column.setSqlType( sqlType );
77+
if ( table.getPrimaryKey().getName() == null ) {
78+
table.getPrimaryKey().setName( name );
79+
}
80+
table.getPrimaryKey().addColumn( column );
81+
}
82+
83+
private void addForeignKeyColumn(Table table, String name, String colName, String sqlType) {
84+
final Column column = table.createColumn( colName );
85+
column.setSqlType( sqlType );
86+
ForeignKey foreignKey = table.locateForeignKey( name );
87+
if ( foreignKey == null ) {
88+
foreignKey = table.createForeignKey( table, name );
89+
}
90+
foreignKey.addColumn( column );
91+
}
92+
}

0 commit comments

Comments
 (0)