This is an automated email from the ASF dual-hosted git repository. abulatski pushed a commit to branch STABLE-4.1 in repository https://gitbox.apache.org/repos/asf/cayenne.git
The following commit(s) were added to refs/heads/STABLE-4.1 by this push: new 8d5a9fe CAY-2600 Modeler DbImport: Can't retrieve schema for databases with no catalog support 8d5a9fe is described below commit 8d5a9fe1f0b228cd7668c3599c5aa73ad28fa252 Author: Arseni Bulatski <ancars...@gmail.com> AuthorDate: Fri Aug 23 16:18:05 2019 +0300 CAY-2600 Modeler DbImport: Can't retrieve schema for databases with no catalog support (cherry picked from commit dc088800eab47bd6b8a34144ef051d6f8c155879) --- .../java/org/apache/cayenne/dba/AutoAdapter.java | 28 +++- .../java/org/apache/cayenne/dba/DbAdapter.java | 23 ++- .../java/org/apache/cayenne/dba/JdbcAdapter.java | 12 +- .../org/apache/cayenne/dba/mysql/MySQLAdapter.java | 13 +- .../apache/cayenne/dba/oracle/OracleAdapter.java | 36 +++-- .../cayenne/dba/sqlserver/SQLServerAdapter.java | 18 ++- .../cayenne/modeler/action/LoadDbSchemaAction.java | 3 +- .../editor/dbimport/DatabaseSchemaLoader.java | 168 +++++++++++---------- .../modeler/editor/dbimport/DbImportTree.java | 64 +++++--- 9 files changed, 231 insertions(+), 134 deletions(-) diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java index 44f1b25..77ef360 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java @@ -7,7 +7,7 @@ * "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 + * https://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 @@ -19,6 +19,12 @@ package org.apache.cayenne.dba; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.access.DataNode; import org.apache.cayenne.access.translator.ParameterBinding; @@ -37,15 +43,11 @@ import org.apache.cayenne.query.Query; import org.apache.cayenne.query.SQLAction; import org.apache.cayenne.query.SelectQuery; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.Collection; - /** * A DbAdapter that automatically detects the kind of database it is running on * and instantiates an appropriate DB-specific adapter, delegating all * subsequent method calls to this adapter. - * + * * @since 1.2 */ public class AutoAdapter implements DbAdapter { @@ -62,7 +64,7 @@ public class AutoAdapter implements DbAdapter { /** * Creates an {@link AutoAdapter} based on a delegate adapter obtained via * "adapterProvider". - * + * * @since 3.1 */ public AutoAdapter(Provider<DbAdapter> adapterProvider, JdbcEventLogger logger) { @@ -96,7 +98,7 @@ public class AutoAdapter implements DbAdapter { protected DbAdapter loadAdapter() { return adapterProvider.get(); } - + /** * @since 4.0 */ @@ -242,4 +244,14 @@ public class AutoAdapter implements DbAdapter { public EJBQLTranslatorFactory getEjbqlTranslatorFactory() { return getAdapter().getEjbqlTranslatorFactory(); } + + @Override + public List<String> getSystemCatalogs() { + return Collections.emptyList(); + } + + @Override + public List<String> getSystemSchemas() { + return Collections.emptyList(); + } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java index ae8073e..3d7988f 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java @@ -7,7 +7,7 @@ * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * <p/> - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * <p/> * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an @@ -18,6 +18,11 @@ ****************************************************************/ package org.apache.cayenne.dba; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Collection; +import java.util.List; + import org.apache.cayenne.access.DataNode; import org.apache.cayenne.access.translator.ParameterBinding; import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory; @@ -33,10 +38,6 @@ import org.apache.cayenne.query.Query; import org.apache.cayenne.query.SQLAction; import org.apache.cayenne.query.SelectQuery; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.Collection; - /** * A Cayenne extension point that abstracts the differences between specifics of * JDBC interfaces to various databases. Cayenne already ships with a number of @@ -221,4 +222,16 @@ public interface DbAdapter { * @since 4.0 */ EJBQLTranslatorFactory getEjbqlTranslatorFactory(); + + /** + * @since 4.1 + * @return list of system catalogs + */ + List<String> getSystemCatalogs(); + + /** + * @since 4.1 + * @return list of system schemas + */ + List<String> getSystemSchemas(); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java index 4db2b38..1f4493b 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java @@ -7,7 +7,7 @@ * "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 + * https://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 @@ -592,6 +592,16 @@ public class JdbcAdapter implements DbAdapter { return ejbqlTranslatorFactory; } + @Override + public List<String> getSystemCatalogs() { + return Collections.emptyList(); + } + + @Override + public List<String> getSystemSchemas() { + return Collections.emptyList(); + } + /** * Sets a translator factory for EJBQL to SQL translation. This property is * normally initialized in constructor by calling diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java index b50fbc0..b7adc4e 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java @@ -7,7 +7,7 @@ * "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 + * https://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 @@ -88,6 +88,8 @@ public class MySQLAdapter extends JdbcAdapter { protected String storageEngine; + private String[] SYSTEM_CATALOGS = new String[]{"sys"}; + public MySQLAdapter(@Inject RuntimeProperties runtimeProperties, @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes, @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes, @@ -123,7 +125,7 @@ public class MySQLAdapter extends JdbcAdapter { /** * Uses special action builder to create the right action. - * + * * @since 1.2 */ @Override @@ -271,7 +273,7 @@ public class MySQLAdapter extends JdbcAdapter { * Customizes PK clause semantics to ensure that generated columns are in * the beginning of the PK definition, as this seems to be a requirement for * InnoDB tables. - * + * * @since 1.2 */ // See CAY-358 for details of the InnoDB problem @@ -363,6 +365,11 @@ public class MySQLAdapter extends JdbcAdapter { } } + @Override + public List<String> getSystemCatalogs() { + return Arrays.asList(SYSTEM_CATALOGS); + } + final class PKComparator implements Comparator<DbAttribute> { public int compare(DbAttribute a1, DbAttribute a2) { diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java index 77f2be1..827d534 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java @@ -7,7 +7,7 @@ * "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 + * https://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 @@ -19,6 +19,17 @@ package org.apache.cayenne.dba.oracle; +import java.lang.reflect.Field; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.access.DataNode; import org.apache.cayenne.access.translator.ParameterBinding; @@ -48,16 +59,6 @@ import org.apache.cayenne.query.SelectQuery; import org.apache.cayenne.query.UpdateBatchQuery; import org.apache.cayenne.resource.ResourceLocator; -import java.lang.reflect.Field; -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - /** * DbAdapter implementation for <a href="http://www.oracle.com">Oracle RDBMS * </a>. Sample connection settings to use with Oracle are shown below: @@ -85,6 +86,14 @@ public class OracleAdapter extends JdbcAdapter { protected static boolean supportsOracleLOB; + private String[] SYSTEM_SCHEMAS = new String[]{ + "ANONYMOUS", "APPQOSSYS", "AUDSYS", "CTXSYS", "DBSFWUSER", + "DBSNMP", "DIP", "DVF", "GGSYS", "DVSYS", "GSMADMIN_INTERNAL", + "GSMCATUSER", "GSMUSER", "LBACSYS", "MDDATA", "MDSYS", "OJVMSYS", + "OLAPSYS", "ORACLE_OCM", "ORDDATA", "ORDPLUGINS", "ORDSYS", "OUTLN", + "REMOTE_SCHEDULER_AGENT", "SYSTEM", "WMSYS", "SI_INFORMTN_SCHEMA", + "SYS", "SYSBACKUP", "SYSDG", "SYSKM", "SYSRAC", "SYS$UMF", "XDB", "XS$NULL"}; + static { // TODO: as CAY-234 shows, having such initialization done in a static // fashion @@ -300,6 +309,11 @@ public class OracleAdapter extends JdbcAdapter { return query.createSQLAction(new OracleActionBuilder(node)); } + @Override + public List<String> getSystemSchemas() { + return Arrays.asList(SYSTEM_SCHEMAS); + } + /** * @since 3.0 */ diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java index a94bf62..3119ee2 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java @@ -7,7 +7,7 @@ * "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 + * https://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 @@ -19,6 +19,7 @@ package org.apache.cayenne.dba.sqlserver; +import java.util.Arrays; import java.util.List; import org.apache.cayenne.access.DataNode; @@ -46,7 +47,7 @@ import org.apache.cayenne.resource.ResourceLocator; * <h3>Microsoft Driver Settings</h3> * <p> * Sample connection settings to use with MS SQL Server are shown below: - * + * * <pre> * sqlserver.jdbc.username = test * sqlserver.jdbc.password = secret @@ -65,20 +66,22 @@ import org.apache.cayenne.resource.ResourceLocator; * "http://jtds.sourceforge.net">http://jtds.sourceforge.net </a>. It supports * both SQLServer and Sybase. Sample SQLServer settings are the following: * </p> - * + * * <pre> * sqlserver.jdbc.username = test * sqlserver.jdbc.password = secret * sqlserver.jdbc.url = jdbc:jtds:sqlserver://192.168.0.65/cayenne * sqlserver.jdbc.driver = net.sourceforge.jtds.jdbc.Driver * </pre> - * + * * @since 1.1 */ public class SQLServerAdapter extends SybaseAdapter { public static final String TRIM_FUNCTION = "RTRIM"; + private String[] SYSTEM_SCHEMAS = new String[]{"dbo", "sys", "INFORMATION_SCHEMA"}; + public SQLServerAdapter(@Inject RuntimeProperties runtimeProperties, @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes, @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes, @@ -100,7 +103,7 @@ public class SQLServerAdapter extends SybaseAdapter { /** * Uses SQLServerActionBuilder to create the right action. - * + * * @since 1.2 */ @Override @@ -118,4 +121,9 @@ public class SQLServerAdapter extends SybaseAdapter { translator.setCaseInsensitive(caseInsensitiveCollations); return translator; } + @Override + public List<String> getSystemSchemas() { + return Arrays.asList(SYSTEM_SCHEMAS); + } + } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java index 5958812..f055a91 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java @@ -22,7 +22,6 @@ package org.apache.cayenne.modeler.action; import javax.swing.JOptionPane; import javax.swing.tree.TreePath; import java.awt.event.ActionEvent; -import java.sql.SQLException; import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering; import org.apache.cayenne.modeler.Application; @@ -104,7 +103,7 @@ public class LoadDbSchemaAction extends CayenneAction { } - } catch (SQLException exception) { + } catch (Exception exception) { JOptionPane.showMessageDialog( Application.getFrame(), exception.getMessage(), diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DatabaseSchemaLoader.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DatabaseSchemaLoader.java index 720541c..fafd9c8 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DatabaseSchemaLoader.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DatabaseSchemaLoader.java @@ -21,10 +21,13 @@ package org.apache.cayenne.modeler.editor.dbimport; import javax.swing.tree.TreePath; import java.sql.Connection; +import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; +import java.util.List; +import org.apache.cayenne.dba.DbAdapter; import org.apache.cayenne.dbsync.reverse.dbimport.Catalog; import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer; import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn; @@ -39,9 +42,6 @@ import org.apache.cayenne.modeler.pref.DBConnectionInfo; public class DatabaseSchemaLoader { private static final String INCLUDE_ALL_PATTERN = "%"; - private static final int TABLE_INDEX = 3; - private static final int SCHEMA_INDEX = 2; - private static final int CATALOG_INDEX = 1; private ReverseEngineering databaseReverseEngineering; @@ -51,94 +51,84 @@ public class DatabaseSchemaLoader { public ReverseEngineering load(DBConnectionInfo connectionInfo, ClassLoadingService loadingService, - String[] tableTypesFromConfig) throws SQLException { + String[] tableTypesFromConfig) throws Exception { + DbAdapter dbAdapter = connectionInfo.makeAdapter(loadingService); try (Connection connection = connectionInfo.makeDataSource(loadingService).getConnection()) { String[] types = tableTypesFromConfig != null && tableTypesFromConfig.length != 0 ? tableTypesFromConfig : new String[]{"TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM"}; - processCatalogs(connection, types); + processCatalogs(connection, types, dbAdapter); } return databaseReverseEngineering; } - private void processCatalogs(Connection connection, String[] types) throws SQLException { - String defaultCatalog = connection.getCatalog(); + private void processCatalogs(Connection connection, String[] types, DbAdapter dbAdapter) throws SQLException { try (ResultSet rsCatalog = connection.getMetaData().getCatalogs()) { boolean hasCatalogs = false; + List<String> systemCatalogs = dbAdapter.getSystemCatalogs(); while (rsCatalog.next()) { hasCatalogs = true; - ResultSet resultSet = connection.getMetaData() - .getTables(processFilter(rsCatalog, defaultCatalog, CATALOG_INDEX), - null, - INCLUDE_ALL_PATTERN, - types); - packTable(resultSet); - packFunctions(connection); + String catalog = rsCatalog.getString("TABLE_CAT"); + if(!systemCatalogs.contains(catalog)) { + processSchemas(connection, types, catalog, dbAdapter); + } } if(!hasCatalogs) { - processSchemas(connection, types); + processSchemas(connection, types, null, dbAdapter); } } } - private void processSchemas(Connection connection, String[] types) throws SQLException { - String defaultSchema = connection.getSchema(); - try(ResultSet rsSchema = connection.getMetaData().getSchemas()) { + private void processSchemas(Connection connection, + String[] types, + String catalog, + DbAdapter dbAdapter) throws SQLException { + DatabaseMetaData metaData = connection.getMetaData(); + try(ResultSet rsSchema = metaData.getSchemas(catalog, null)) { boolean hasSchemas = false; + List<String> systemSchemas = dbAdapter.getSystemSchemas(); while (rsSchema.next()) { hasSchemas = true; - ResultSet resultSet = connection.getMetaData() - .getTables(null, - processFilter(rsSchema, defaultSchema, SCHEMA_INDEX), - INCLUDE_ALL_PATTERN, - types); - packTable(resultSet); - packFunctions(connection); + String schema = rsSchema.getString("TABLE_SCHEM"); + if(!systemSchemas.contains(schema)) { + ResultSet resultSet = metaData.getTables(catalog, schema, INCLUDE_ALL_PATTERN, types); + packTable(resultSet); + packProcedures(connection); + } } if(!hasSchemas) { - ResultSet resultSet = connection.getMetaData() - .getTables(null, - null, - INCLUDE_ALL_PATTERN, - types); - packTable(resultSet); + ResultSet resultSet = metaData.getTables(catalog, null, INCLUDE_ALL_PATTERN, types); packTable(resultSet); + packProcedures(connection); } } } - private void packTable(ResultSet resultSet) throws SQLException { - while (resultSet.next()) { - String tableName = resultSet.getString(TABLE_INDEX); - String schemaName = resultSet.getString(SCHEMA_INDEX); - String catalogName = resultSet.getString(CATALOG_INDEX); - packTable(tableName, catalogName, schemaName, null); - } - } - - private String processFilter(ResultSet resultSet, String defaultFilter, int filterIndex) throws SQLException { - return defaultFilter.isEmpty() ? - resultSet.getString(filterIndex) : - defaultFilter; - } - public ReverseEngineering loadColumns(DBConnectionInfo connectionInfo, ClassLoadingService loadingService, TreePath path) throws SQLException { - Object userObject = ((DbImportTreeNode)path.getPathComponent(1)).getUserObject(); + int pathIndex = 1; String catalogName = null, schemaName = null; + + Object userObject = getUserObject(path, pathIndex); if(userObject instanceof Catalog) { catalogName = ((Catalog) userObject).getName(); + userObject = getUserObject(path, ++pathIndex); + if(userObject instanceof Schema) { + schemaName = ((Schema) userObject).getName(); + userObject = getUserObject(path, ++pathIndex); + } } else if(userObject instanceof Schema) { schemaName = ((Schema) userObject).getName(); + userObject = getUserObject(path, ++pathIndex); } - String tableName = path.getPathComponent(2).toString(); + String tableName = processTable(userObject); try (Connection connection = connectionInfo.makeDataSource(loadingService).getConnection()) { try (ResultSet rs = connection.getMetaData().getColumns(catalogName, schemaName, tableName, null)) { while (rs.next()) { - String column = rs.getString(4); + String column = rs.getString("COLUMN_NAME"); packTable(tableName, catalogName, schemaName, column); } } @@ -146,45 +136,62 @@ public class DatabaseSchemaLoader { return databaseReverseEngineering; } - private void packFunctions(Connection connection) throws SQLException { + private Object getUserObject(TreePath path, int pathIndex) { + return ((DbImportTreeNode)path.getPathComponent(pathIndex)).getUserObject(); + } + + private String processTable(Object userObject) { + if(userObject instanceof IncludeTable) { + return ((IncludeTable) userObject).getPattern(); + } + return null; + } + + private void packProcedures(Connection connection) throws SQLException { Collection<Catalog> catalogs = databaseReverseEngineering.getCatalogs(); - for (Catalog catalog : catalogs) { - ResultSet procResultSet = connection.getMetaData().getProcedures( - catalog.getName(), null, "%" - ); - while (procResultSet.next()) { - IncludeProcedure includeProcedure = new IncludeProcedure(procResultSet.getString(3)); - if (!catalog.getIncludeProcedures().contains(includeProcedure)) { - catalog.addIncludeProcedure(includeProcedure); + for(Catalog catalog : catalogs) { + Collection<Schema> schemas = catalog.getSchemas(); + if(!schemas.isEmpty()) { + for(Schema schema : schemas) { + ResultSet procResultSet = getProcedures(connection, catalog.getName(), schema.getName()); + packFunction(procResultSet, schema); } + } else { + ResultSet procResultSet = getProcedures(connection, catalog.getName(), null); + packFunction(procResultSet, catalog); } } - for (Schema schema : databaseReverseEngineering.getSchemas()) { - ResultSet procResultSet = connection.getMetaData().getProcedures( - null, schema.getName(), "%" - ); - while (procResultSet.next()) { - IncludeProcedure includeProcedure = new IncludeProcedure(procResultSet.getString(3)); - if (!schema.getIncludeProcedures().contains(includeProcedure)) { - schema.addIncludeProcedure(includeProcedure); - } - } + + Collection<Schema> schemas = databaseReverseEngineering.getSchemas(); + for(Schema schema : schemas) { + ResultSet procResultSet = getProcedures(connection, null, schema.getName()); + packFunction(procResultSet, schema); } - for (Catalog catalog : catalogs) { - for (Schema schema : catalog.getSchemas()) { - ResultSet procResultSet = connection.getMetaData().getProcedures( - catalog.getName(), schema.getName(), "%" - ); - while (procResultSet.next()) { - IncludeProcedure includeProcedure = new IncludeProcedure(procResultSet.getString(3)); - if (!schema.getIncludeProcedures().contains(includeProcedure)) { - schema.addIncludeProcedure(includeProcedure); - } - } + } + + private ResultSet getProcedures(Connection connection, String catalog, String schema) throws SQLException { + return connection.getMetaData().getProcedures(catalog, schema, "%"); + } + + private void packFunction(ResultSet resultSet, FilterContainer filterContainer) throws SQLException { + while (resultSet.next()) { + IncludeProcedure includeProcedure = + new IncludeProcedure(resultSet.getString("PROCEDURE_NAME")); + if (!filterContainer.getIncludeProcedures().contains(includeProcedure)) { + filterContainer.addIncludeProcedure(includeProcedure); } } } + private void packTable(ResultSet resultSet) throws SQLException { + while (resultSet.next()) { + String tableName = resultSet.getString("TABLE_NAME"); + String schemaName = resultSet.getString("TABLE_SCHEM"); + String catalogName = resultSet.getString("TABLE_CAT"); + packTable(tableName, catalogName, schemaName, null); + } + } + private void packTable(String tableName, String catalogName, String schemaName, String columnName) { IncludeTable table = new IncludeTable(); table.setPattern(tableName); @@ -230,6 +237,7 @@ public class DatabaseSchemaLoader { parentCatalog.setName(catalogName); parentSchema = new Schema(); parentSchema.setName(schemaName); + parentCatalog.addSchema(parentSchema); databaseReverseEngineering.addCatalog(parentCatalog); } filterContainer = parentSchema; @@ -248,7 +256,7 @@ public class DatabaseSchemaLoader { private void addColumn(FilterContainer filterContainer, IncludeTable table, String columnName) { IncludeTable foundTable = getTableByName(filterContainer.getIncludeTables(), table.getPattern()); table = foundTable != null ? foundTable : table; - if (columnName != null ) { + if (columnName != null) { IncludeColumn includeColumn = new IncludeColumn(columnName); table.addIncludeColumn(includeColumn); } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java index fdc497b..08ec582 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java @@ -75,35 +75,61 @@ public class DbImportTree extends JTree { public void updateTableColumns(ReverseEngineering reverseEngineering) { DbImportModel model = (DbImportModel) this.getModel(); - DbImportTreeNode root = (DbImportTreeNode) model.getRoot(); Collection<Catalog> catalogs = reverseEngineering.getCatalogs(); - Collection<? extends FilterContainer> filterContainers = !catalogs.isEmpty() ? - catalogs : - reverseEngineering.getSchemas(); - filterContainers.forEach(filterContainer -> { - DbImportTreeNode container = findNodeInParent(root, filterContainer); + if(!catalogs.isEmpty()) { + catalogs.forEach(catalog -> { + Collection<Schema> schemas = catalog.getSchemas(); + if(!schemas.isEmpty()) { + DbImportTreeNode currentRoot = findNodeInParent(root, catalog); + schemas.forEach(schema -> packNextFilter(schema, currentRoot, model)); + } else { + packNextFilter(catalog, root, model); + } + }); + } else { + reverseEngineering.getSchemas().forEach(schema -> { + packNextFilter(schema, root, model); + }); + } + } + + private void packNextFilter(FilterContainer filterContainer, + DbImportTreeNode root, + DbImportModel model) { + DbImportTreeNode container = findNodeInParent(root, filterContainer); + if (container == null) { + return; + } + + packTables(filterContainer, container, model); + } + + private void packTables(FilterContainer filterContainer, + DbImportTreeNode root, + DbImportModel model) { + filterContainer.getIncludeTables().forEach(tableFilter -> { + DbImportTreeNode container = findNodeInParent(root, tableFilter ); if (container == null) { return; } + if (container.getChildCount() != 0) { + container.removeAllChildren(); + } - filterContainer.getIncludeTables().forEach(newTable -> { - DbImportTreeNode table = findNodeInParent(container, newTable); - if (table == null) { - return; - } - if (table.getChildCount() != 0) { - table.removeAllChildren(); - } - newTable.getIncludeColumns().forEach(column -> - table.add(new DbImportTreeNode(column))); - table.setLoaded(true); - model.reload(table); - }); + packColumns(tableFilter , container); + + container.setLoaded(true); + model.reload(container); }); } + private void packColumns(IncludeTable includeTable, DbImportTreeNode tableNode) { + includeTable.getIncludeColumns().forEach(column -> + tableNode.add(new DbImportTreeNode(column))); + } + private DbImportTreeNode findNodeInParent(DbImportTreeNode parent, Object object) { for (int i = 0; i < parent.getChildCount(); i++) { DbImportTreeNode node = (DbImportTreeNode) parent.getChildAt(i);