Index: src/java/org/hibernate/cfg/JDBCBinder.java =================================================================== --- src/java/org/hibernate/cfg/JDBCBinder.java (revision 19955) +++ src/java/org/hibernate/cfg/JDBCBinder.java (working copy) @@ -117,7 +117,7 @@ schema = schema!=null ? schema : settings.getDefaultSchemaName(); JDBCReader reader = JDBCReaderFactory.newJDBCReader(cfg.getProperties(),settings,revengStrategy); - DatabaseCollector dbs = new MappingsDatabaseCollector(mappings); + DatabaseCollector dbs = new MappingsDatabaseCollector(mappings, reader.getMetaDataDialect()); reader.readDatabaseSchema(dbs, catalog, schema); return dbs; } Index: src/java/org/hibernate/cfg/reveng/AbstractDatabaseCollector.java =================================================================== --- src/java/org/hibernate/cfg/reveng/AbstractDatabaseCollector.java (revision 19955) +++ src/java/org/hibernate/cfg/reveng/AbstractDatabaseCollector.java (working copy) @@ -3,13 +3,17 @@ import java.util.HashMap; import java.util.Map; +import org.hibernate.cfg.reveng.dialect.MetaDataDialect; + public abstract class AbstractDatabaseCollector implements DatabaseCollector { private Map oneToManyCandidates; protected final Map suggestedIdentifierStrategies; + private MetaDataDialect dialect; - public AbstractDatabaseCollector() { + public AbstractDatabaseCollector(MetaDataDialect dialect) { suggestedIdentifierStrategies = new HashMap(); + this.dialect = dialect; } public void setOneToManyCandidates(Map oneToManyCandidates) { @@ -29,5 +33,19 @@ TableIdentifier identifier = new TableIdentifier(catalog, schema, name); suggestedIdentifierStrategies.put(identifier, idstrategy); } + + public String quote(String name) { + if (name == null) + return name; + if (dialect.needQuote(name)) { + if (name.length() > 1 && name.charAt(0) == '`' + && name.charAt(name.length() - 1) == '`') { + return name; // avoid double quoting + } + return "`" + name + "`"; + } else { + return name; + } + } } Index: src/java/org/hibernate/cfg/reveng/DefaultDatabaseCollector.java =================================================================== --- src/java/org/hibernate/cfg/reveng/DefaultDatabaseCollector.java (revision 19955) +++ src/java/org/hibernate/cfg/reveng/DefaultDatabaseCollector.java (working copy) @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; +import org.hibernate.cfg.reveng.dialect.MetaDataDialect; import org.hibernate.mapping.Table; import org.hibernate.util.StringHelper; @@ -13,13 +14,13 @@ private Map tables; private Map qualifiers; - public DefaultDatabaseCollector() { + + public DefaultDatabaseCollector(MetaDataDialect dialect) { + super(dialect); tables = new HashMap(); - qualifiers = new HashMap(); + qualifiers = new HashMap(); } - - public Iterator iterateTables() { return tables.values().iterator(); } @@ -28,7 +29,7 @@ String catalog, String name) { - String key = Table.qualify(catalog, schema, name); + String key = Table.qualify(quote(catalog), quote(schema), quote(name)); Table table = (Table) tables.get(key); if (table == null) { @@ -55,11 +56,13 @@ } public Table getTable(String schema, String catalog, String name) { - String key = Table.qualify(catalog, schema, name); + String key = Table.qualify(quote(catalog), quote(schema), quote(name)); return (Table) tables.get(key); } public Iterator getQualifierEntries() { return qualifiers.entrySet().iterator(); } + + } Index: src/java/org/hibernate/cfg/reveng/JDBCReader.java =================================================================== --- src/java/org/hibernate/cfg/reveng/JDBCReader.java (revision 20308) +++ src/java/org/hibernate/cfg/reveng/JDBCReader.java (working copy) @@ -549,7 +549,7 @@ } log.debug("Adding table " + tableName + " of type " + tableType); progress.startSubTask("Found " + tableName); - Table table = dbs.addTable(quote(getSchemaForModel(schemaName)), getCatalogForModel(catalogName), quote(tableName)); + Table table = dbs.addTable(getSchemaForModel(schemaName), getCatalogForModel(catalogName), quote(tableName)); table.setComment(comment); if(tableType.equalsIgnoreCase("TABLE")) { hasIndices.add(table); @@ -668,7 +668,7 @@ } - private String quote(String columnName) { + public String quote(String columnName) { if(columnName==null) return columnName; if(getMetaDataDialect().needQuote(columnName)) { if(columnName.length()>1 && columnName.charAt(0)=='`' && columnName.charAt(columnName.length()-1)=='`') { @@ -680,7 +680,7 @@ } } - private MetaDataDialect getMetaDataDialect() { + public MetaDataDialect getMetaDataDialect() { return metadataDialect; } Index: src/java/org/hibernate/cfg/reveng/MappingsDatabaseCollector.java =================================================================== --- src/java/org/hibernate/cfg/reveng/MappingsDatabaseCollector.java (revision 19955) +++ src/java/org/hibernate/cfg/reveng/MappingsDatabaseCollector.java (working copy) @@ -3,13 +3,15 @@ import java.util.Iterator; import org.hibernate.cfg.Mappings; +import org.hibernate.cfg.reveng.dialect.MetaDataDialect; import org.hibernate.mapping.Table; public class MappingsDatabaseCollector extends AbstractDatabaseCollector { private final Mappings mappings; - public MappingsDatabaseCollector(Mappings mappings) { + public MappingsDatabaseCollector(Mappings mappings, MetaDataDialect dialect) { + super(dialect); this.mappings = mappings; } @@ -18,11 +20,11 @@ } public Table addTable(String schema, String catalog, String name) { - return mappings.addTable(schema, catalog, name, null, false); + return mappings.addTable(quote(catalog), quote(schema), quote(name), null, false); } public Table getTable(String schema, String catalog, String name) { - return mappings.getTable(schema, catalog, name); + return mappings.getTable(quote(catalog), quote(schema), quote(name)); } } Index: src/java/org/hibernate/cfg/reveng/dialect/AbstractMetaDataDialect.java =================================================================== --- src/java/org/hibernate/cfg/reveng/dialect/AbstractMetaDataDialect.java (revision 19955) +++ src/java/org/hibernate/cfg/reveng/dialect/AbstractMetaDataDialect.java (working copy) @@ -145,6 +145,7 @@ // TODO: use jdbc metadata to decide on this. but for now we just handle the most typical cases. if(name.indexOf('-')>0) return true; if(name.indexOf(' ')>0) return true; + if(name.indexOf('.')>0) return true; return false; } Index: src/java/org/hibernate/tool/hbmlint/detector/SchemaByMetaDataDetector.java =================================================================== --- src/java/org/hibernate/tool/hbmlint/detector/SchemaByMetaDataDetector.java (revision 19955) +++ src/java/org/hibernate/tool/hbmlint/detector/SchemaByMetaDataDetector.java (working copy) @@ -63,7 +63,7 @@ new DefaultReverseEngineeringStrategy() ); reader = JDBCReaderFactory.newJDBCReader( cfg.getProperties(), settings, tableSelector ); - dbc = new DefaultDatabaseCollector(); + dbc = new DefaultDatabaseCollector(reader.getMetaDataDialect()); mapping = cfg.buildMapping(); } Index: src/test/org/hibernate/tool/BaseTestCase.java =================================================================== --- src/test/org/hibernate/tool/BaseTestCase.java (revision 19955) +++ src/test/org/hibernate/tool/BaseTestCase.java (working copy) @@ -149,7 +149,7 @@ JDBCMetaDataDialect dialect = new JDBCMetaDataDialect(); - dialect.configure( ReverseEngineeringRuntimeInfo.createInstance(testSettings.getConnectionProvider(), testSettings.getSQLExceptionConverter(), new DefaultDatabaseCollector())); + dialect.configure( ReverseEngineeringRuntimeInfo.createInstance(testSettings.getConnectionProvider(), testSettings.getSQLExceptionConverter(), new DefaultDatabaseCollector(dialect))); Iterator tables = dialect.getTables( testSettings.getDefaultCatalogName(), testSettings.getDefaultSchemaName(), null ); assertHasNext( 0, tables ); Index: src/test/org/hibernate/tool/hbm2x/CachedMetaDataTest.java =================================================================== --- src/test/org/hibernate/tool/hbm2x/CachedMetaDataTest.java (revision 19955) +++ src/test/org/hibernate/tool/hbm2x/CachedMetaDataTest.java (working copy) @@ -124,7 +124,7 @@ JDBCReader reader = JDBCReaderFactory.newJDBCReader( buildSettings, new DefaultReverseEngineeringStrategy(), dialect ); - DatabaseCollector dc = new DefaultDatabaseCollector(); + DatabaseCollector dc = new DefaultDatabaseCollector(reader.getMetaDataDialect()); reader.readDatabaseSchema( dc, null, null ); validate( dc ); @@ -133,7 +133,7 @@ reader = JDBCReaderFactory.newJDBCReader( buildSettings, new DefaultReverseEngineeringStrategy(), dialect ); - dc = new DefaultDatabaseCollector(); + dc = new DefaultDatabaseCollector(reader.getMetaDataDialect()); reader.readDatabaseSchema( dc, null, null ); validate(dc); Index: src/test/org/hibernate/tool/hbm2x/DefaultDatabaseCollectorTest.java =================================================================== --- src/test/org/hibernate/tool/hbm2x/DefaultDatabaseCollectorTest.java (revision 0) +++ src/test/org/hibernate/tool/hbm2x/DefaultDatabaseCollectorTest.java (revision 0) @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright (c) 2010 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributor: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.hibernate.tool.hbm2x; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.hibernate.cfg.JDBCMetaDataConfiguration; +import org.hibernate.cfg.JDBCReaderFactory; +import org.hibernate.cfg.Settings; +import org.hibernate.cfg.reveng.DatabaseCollector; +import org.hibernate.cfg.reveng.DefaultDatabaseCollector; +import org.hibernate.cfg.reveng.DefaultReverseEngineeringStrategy; +import org.hibernate.cfg.reveng.JDBCReader; +import org.hibernate.cfg.reveng.OverrideRepository; +import org.hibernate.cfg.reveng.SchemaSelection; +import org.hibernate.cfg.reveng.TableIdentifier; +import org.hibernate.cfg.reveng.dialect.MetaDataDialect; +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.PostgreSQLDialect; +import org.hibernate.mapping.Table; +import org.hibernate.tool.JDBCMetaDataBinderTestCase; + +/** + * @author Dmitry Geraskov + * + */ +public class DefaultDatabaseCollectorTest extends JDBCMetaDataBinderTestCase { + + private static final String SCHEMA = "cat.cat"; + + private static final String QSCHEMA = "\"cat.cat\""; + + public void testReadOnlySpecificSchema() { + + JDBCMetaDataConfiguration configuration = new JDBCMetaDataConfiguration(); + + OverrideRepository or = new OverrideRepository(); + or.addSchemaSelection(new SchemaSelection(null, SCHEMA)); + configuration.setReverseEngineeringStrategy(or.getReverseEngineeringStrategy(new DefaultReverseEngineeringStrategy())); + configuration.readFromJDBC(); + + List tables = getTables(configuration); + + assertEquals(2,tables.size()); + + Table catchild = (Table) tables.get(0); + Table catmaster = (Table) tables.get(1); + + System.out.println(catchild); + System.out.println(catmaster); + + if(catchild.getName().equals("cat.master")) { + catchild = (Table) tables.get(1); + catmaster = (Table) tables.get(0); + } + + TableIdentifier masterid = TableIdentifier.create(catmaster); + TableIdentifier childid = TableIdentifier.create(catchild); + + assertEquals(new TableIdentifier(null, "cat.cat", "cat.child"), childid); + assertEquals(new TableIdentifier(null, "cat.cat", "cat.master"), masterid); + } + + public void testNeedQuote() { + Settings buildSettings = cfg.buildSettings(); + + MetaDataDialect realMetaData = JDBCReaderFactory.newMetaDataDialect( buildSettings.getDialect(), cfg.getProperties() ); + assertTrue("The name must be quoted!", realMetaData.needQuote(SCHEMA)); + assertTrue("The name must be quoted!", realMetaData.needQuote("cat.child")); + assertTrue("The name must be quoted!", realMetaData.needQuote("cat.master")); + } + + /** + * There are 2 solutions: + * 1. DatabaseCollector#addTable()/getTable() should be called for not quoted parameters - I think it is preferable way. + * 2. DatabaseCollector#addTable()/getTable() should be called for quoted parameters - here users should + * use the same quotes as JDBCReader. + * Because of this there are 2 opposite methods(and they are both failed as addTable uses quoted names + * but getTable uses non-quoted names ) + */ + public void testQuatedNamesAndDefaultDatabaseCollector() { + Settings buildSettings = cfg.buildSettings(); + + MetaDataDialect realMetaData = JDBCReaderFactory.newMetaDataDialect( buildSettings.getDialect(), cfg.getProperties() ); + + JDBCReader reader = JDBCReaderFactory.newJDBCReader( buildSettings, new DefaultReverseEngineeringStrategy(), realMetaData ); + + DatabaseCollector dc = new DefaultDatabaseCollector(reader.getMetaDataDialect()); + reader.readDatabaseSchema( dc, null, SCHEMA ); + + assertNotNull("The table should be found", dc.getTable(SCHEMA, null, "cat.child")); + assertNotNull("The table should be found", dc.getTable(SCHEMA, null, "cat.master")); + assertNull("Quoted names should not return the table", dc.getTable(quote(SCHEMA), null, quote("cat.child"))); + assertNull("Quoted names should not return the table", dc.getTable(quote(SCHEMA), null, quote("cat.master"))); + + assertEquals("Foreign key 'masterref' was filtered!", 1, dc.getOneToManyCandidates().size()); + } + + /*public void testQuatedNamesAndDefaultDatabaseCollector2() { + Settings buildSettings = cfg.buildSettings(); + + MetaDataDialect realMetaData = JDBCReaderFactory.newMetaDataDialect( buildSettings.getDialect(), cfg.getProperties() ); + + JDBCReader reader = JDBCReaderFactory.newJDBCReader( buildSettings, new DefaultReverseEngineeringStrategy(), realMetaData ); + + DatabaseCollector dc = new DefaultDatabaseCollector(); + reader.readDatabaseSchema( dc, null, SCHEMA ); + + assertNotNull("The table should be found", dc.getTable(quote(SCHEMA), null, quote("cat.child"))); + assertNotNull("The table should be found", dc.getTable(quote(SCHEMA), null, quote("cat.master"))); + assertNull("Quoted names should return the table", dc.getTable(SCHEMA, null, "cat.child")); + assertNull("Quoted names should return the table", dc.getTable(SCHEMA, null, "cat.master")); + + assertEquals("Foreign key 'masterref' was filtered!", 1, dc.getOneToManyCandidates().size()); + }*/ + + private String quote(String name) { + return "`" + name + "`"; + + } + + private List getTables(JDBCMetaDataConfiguration metaDataConfiguration) { + List list = new ArrayList(); + Iterator iter = metaDataConfiguration.getTableMappings(); + while(iter.hasNext()) { + Table element = (Table) iter.next(); + list.add(element); + } + return list; + } + + protected void tearDown() throws Exception { + executeDDL(getDropSQL(), false); + } + + protected String[] getCreateSQL() { + return new String[] { + "create schema " + QSCHEMA, + "create table " + QSCHEMA + ".\"cat.master\" (" + + " id integer NOT NULL," + + " tt integer," + + " CONSTRAINT master_pk PRIMARY KEY (id)" + + ")", + "create table " + QSCHEMA + ".\"cat.child\" (" + + " childid integer NOT NULL,\r\n" + + " masterref integer,\r\n" + + " CONSTRAINT child_pk PRIMARY KEY (childid),\r\n" + + " CONSTRAINT masterref FOREIGN KEY (masterref) references "+ QSCHEMA + ".\"cat.master\"(id)" + + ")", + }; + } + + protected String[] getDropSQL() { + + return new String[] { + "drop table " + QSCHEMA + ".\"cat.child\"", + "drop table " + QSCHEMA + ".\"cat.master\"", + "drop schema " + QSCHEMA + }; + } + + public boolean appliesTo(Dialect dialect) { + return dialect instanceof PostgreSQLDialect; + } + +} Index: src/test/org/hibernate/tool/hbm2x/IncrementalSchemaReadingTest.java =================================================================== --- src/test/org/hibernate/tool/hbm2x/IncrementalSchemaReadingTest.java (revision 19955) +++ src/test/org/hibernate/tool/hbm2x/IncrementalSchemaReadingTest.java (working copy) @@ -51,7 +51,7 @@ tss.addSchemaSelection( new SchemaSelection(null,null, "CHILD") ); - DatabaseCollector dc = new DefaultDatabaseCollector(); + DatabaseCollector dc = new DefaultDatabaseCollector(reader.getMetaDataDialect()); reader.readDatabaseSchema( dc, null, null ); assertEquals(mockedMetaDataDialect.gottenTables.size(),1); Index: src/test/org/hibernate/tool/test/DriverMetaDataTest.java =================================================================== --- src/test/org/hibernate/tool/test/DriverMetaDataTest.java (revision 19955) +++ src/test/org/hibernate/tool/test/DriverMetaDataTest.java (working copy) @@ -41,7 +41,7 @@ Settings settings = cfg.buildSettings(); - dialect.configure( ReverseEngineeringRuntimeInfo.createInstance(settings.getConnectionProvider(), settings.getSQLExceptionConverter(), new DefaultDatabaseCollector())); + dialect.configure( ReverseEngineeringRuntimeInfo.createInstance(settings.getConnectionProvider(), settings.getSQLExceptionConverter(), new DefaultDatabaseCollector(dialect))); Iterator tables = dialect.getTables( settings.getDefaultCatalogName(), settings.getDefaultSchemaName(), identifier("tab_master") ); @@ -76,7 +76,7 @@ Settings settings = cfg.buildSettings(); - dialect.configure( ReverseEngineeringRuntimeInfo.createInstance(settings.getConnectionProvider(), settings.getSQLExceptionConverter(), new DefaultDatabaseCollector())); + dialect.configure( ReverseEngineeringRuntimeInfo.createInstance(settings.getConnectionProvider(), settings.getSQLExceptionConverter(), new DefaultDatabaseCollector(dialect))); Iterator tables = dialect.getColumns( settings.getDefaultCatalogName(), settings.getDefaultSchemaName(), "test", null ); @@ -96,7 +96,7 @@ Settings settings = cfg.buildSettings(); - dialect.configure( ReverseEngineeringRuntimeInfo.createInstance(settings.getConnectionProvider(), settings.getSQLExceptionConverter(), new DefaultDatabaseCollector())); + dialect.configure( ReverseEngineeringRuntimeInfo.createInstance(settings.getConnectionProvider(), settings.getSQLExceptionConverter(), new DefaultDatabaseCollector(dialect))); Iterator tables = dialect.getTables( settings.getDefaultCatalogName(), settings.getDefaultSchemaName(), identifier( "TAB_MASTER"));