IGNITE-3144 Refactor Schema Import Utility. Split for two modules: schema-import and schema-import-db.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/fa197d2f Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/fa197d2f Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/fa197d2f Branch: refs/heads/master Commit: fa197d2f71430cb5e8765335eff6a9c2d4f6ec10 Parents: c9f9d24 Author: Alexey Kuznetsov <[email protected]> Authored: Tue May 17 14:22:23 2016 +0700 Committer: Alexey Kuznetsov <[email protected]> Committed: Tue May 17 14:22:23 2016 +0700 ---------------------------------------------------------------------- assembly/dependencies-schema-import.xml | 1 + assembly/release-schema-import.xml | 2 +- modules/schema-import-db/README.txt | 4 + modules/schema-import-db/pom.xml | 44 ++ .../apache/ignite/schema/parser/DbColumn.java | 76 +++ .../ignite/schema/parser/DbMetadataReader.java | 147 ++++++ .../apache/ignite/schema/parser/DbTable.java | 82 +++ .../parser/dialect/DB2MetadataDialect.java | 33 ++ .../parser/dialect/DatabaseMetadataDialect.java | 75 +++ .../parser/dialect/JdbcMetadataDialect.java | 197 +++++++ .../parser/dialect/MySQLMetadataDialect.java | 62 +++ .../parser/dialect/OracleMetadataDialect.java | 364 +++++++++++++ modules/schema-import/pom.xml | 6 + .../schema/parser/DatabaseMetadataParser.java | 44 +- .../apache/ignite/schema/parser/DbColumn.java | 76 --- .../apache/ignite/schema/parser/DbTable.java | 82 --- .../parser/dialect/DB2MetadataDialect.java | 33 -- .../parser/dialect/DatabaseMetadataDialect.java | 75 --- .../parser/dialect/JdbcMetadataDialect.java | 197 ------- .../parser/dialect/MySQLMetadataDialect.java | 61 --- .../parser/dialect/OracleMetadataDialect.java | 364 ------------- .../ignite/schema/ui/SchemaImportApp.java | 526 ++++++++----------- pom.xml | 2 + 23 files changed, 1328 insertions(+), 1225 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/assembly/dependencies-schema-import.xml ---------------------------------------------------------------------- diff --git a/assembly/dependencies-schema-import.xml b/assembly/dependencies-schema-import.xml index 53c32c2..d7aa3ae 100644 --- a/assembly/dependencies-schema-import.xml +++ b/assembly/dependencies-schema-import.xml @@ -33,6 +33,7 @@ <moduleSet> <includes> <include>org.apache.ignite:ignite-schema-import</include> + <include>org.apache.ignite:ignite-schema-import-db</include> </includes> <sources> <includeModuleDirectory>false</includeModuleDirectory> http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/assembly/release-schema-import.xml ---------------------------------------------------------------------- diff --git a/assembly/release-schema-import.xml b/assembly/release-schema-import.xml index b746c83..38457b9 100644 --- a/assembly/release-schema-import.xml +++ b/assembly/release-schema-import.xml @@ -21,7 +21,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd"> - <id>scala</id> + <id>release-schema-import</id> <includeBaseDirectory>false</includeBaseDirectory> http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import-db/README.txt ---------------------------------------------------------------------- diff --git a/modules/schema-import-db/README.txt b/modules/schema-import-db/README.txt new file mode 100644 index 0000000..556e1c6 --- /dev/null +++ b/modules/schema-import-db/README.txt @@ -0,0 +1,4 @@ +Apache Ignite Schema Import DB Module +------------------------------------------ + +Utility classes to extract database metadata. http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import-db/pom.xml ---------------------------------------------------------------------- diff --git a/modules/schema-import-db/pom.xml b/modules/schema-import-db/pom.xml new file mode 100644 index 0000000..337f39a --- /dev/null +++ b/modules/schema-import-db/pom.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + 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. +--> + +<!-- + POM file. +--> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-parent</artifactId> + <version>1</version> + <relativePath>../../parent</relativePath> + </parent> + + <artifactId>ignite-schema-import-db</artifactId> + <version>1.6.0-SNAPSHOT</version> + + <dependencies> + <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-core</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbColumn.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbColumn.java b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbColumn.java new file mode 100644 index 0000000..8b0c813 --- /dev/null +++ b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbColumn.java @@ -0,0 +1,76 @@ +/* + * 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.apache.ignite.schema.parser; + +/** + * Database table column. + */ +public class DbColumn { + /** Column name. */ + private final String name; + + /** Column JDBC type. */ + private final int type; + + /** Is this column belongs to primary key. */ + private final boolean key; + + /** Is {@code NULL} allowed for column in database. */ + private final boolean nullable; + + /** + * @param name Column name. + * @param type Column JDBC type. + * @param key {@code true} if this column belongs to primary key. + * @param nullable {@code true} if {@code NULL } allowed for column in database. + */ + public DbColumn(String name, int type, boolean key, boolean nullable) { + this.name = name; + this.type = type; + this.key = key; + this.nullable = nullable; + } + + /** + * @return Column name. + */ + public String name() { + return name; + } + + /** + * @return Column JDBC type. + */ + public int type() { + return type; + } + + /** + * @return {@code true} if this column belongs to primary key. + */ + public boolean key() { + return key; + } + + /** + * @return nullable {@code true} if {@code NULL } allowed for column in database. + */ + public boolean nullable() { + return nullable; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbMetadataReader.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbMetadataReader.java b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbMetadataReader.java new file mode 100644 index 0000000..5b45f33 --- /dev/null +++ b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbMetadataReader.java @@ -0,0 +1,147 @@ +/* + * 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.apache.ignite.schema.parser; + +import org.apache.ignite.schema.parser.dialect.*; + +import java.io.*; +import java.net.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +/** + * Singleton to extract database metadata. + */ +public class DbMetadataReader { + /** Logger. */ + private static final Logger log = Logger.getLogger(DbMetadataReader.class.getName()); + + /** */ + private static final DbMetadataReader INSTANCE = new DbMetadataReader(); + + /** */ + private final Map<String, Driver> drivers = new HashMap<>(); + + /** + * Default constructor. + */ + private DbMetadataReader() { + // No-op. + } + + /** + * @return Instance. + */ + public static DbMetadataReader getInstance() { + return INSTANCE; + } + + /** + * Get specified dialect object for selected database. + * + * @param conn Connection to database. + * @return Specific dialect object. + */ + private DatabaseMetadataDialect dialect(Connection conn) { + try { + String dbProductName = conn.getMetaData().getDatabaseProductName(); + + if ("Oracle".equals(dbProductName)) + return new OracleMetadataDialect(); + else if (dbProductName.startsWith("DB2/")) + return new DB2MetadataDialect(); + else if (dbProductName.equals("MySQL")) + return new MySQLMetadataDialect(); + else + return new JdbcMetadataDialect(); + } + catch (SQLException e) { + log.log(Level.SEVERE, "Failed to resolve dialect (JdbcMetaDataDialect will be used.", e); + + return new JdbcMetadataDialect(); + } + } + + /** + * Get list of schemas from database. + * + * @param conn Connection to database. + * @return List of schema names. + * @throws SQLException If schemas loading failed. + */ + public Collection<String> schemas(Connection conn) throws SQLException { + return dialect(conn).schemas(conn); + } + + /** + * Extract DB metadata. + * + * @param conn Connection. + * @param schemas List of database schemas to process. In case of empty list all schemas will be processed. + * @param tblsOnly Tables only flag. + */ + public Collection<DbTable> metadata(Connection conn, List<String> schemas, boolean tblsOnly) throws SQLException { + return dialect(conn).tables(conn, schemas, tblsOnly); + } + + /** + * Connect to database. + * + * @param jdbcDrvJarPath Path to JDBC driver. + * @param jdbcDrvCls JDBC class name. + * @param jdbcUrl JDBC connection URL. + * @param jdbcInfo Connection properties. + * @return Connection to database. + * @throws SQLException if connection failed. + */ + public Connection connect(String jdbcDrvJarPath, String jdbcDrvCls, String jdbcUrl, Properties jdbcInfo) + throws SQLException { + Driver drv = drivers.get(jdbcDrvCls); + + if (drv == null) { + if (jdbcDrvJarPath.isEmpty()) + throw new IllegalStateException("Driver jar file name is not specified."); + + File drvJar = new File(jdbcDrvJarPath); + + if (!drvJar.exists()) + throw new IllegalStateException("Driver jar file is not found."); + + try { + URL u = new URL("jar:" + drvJar.toURI() + "!/"); + + URLClassLoader ucl = URLClassLoader.newInstance(new URL[] {u}); + + drv = (Driver)Class.forName(jdbcDrvCls, true, ucl).newInstance(); + + drivers.put(jdbcDrvCls, drv); + } + catch (Exception e) { + throw new IllegalStateException(e); + } + } + + Connection conn = drv.connect(jdbcUrl, jdbcInfo); + + if (conn == null) + throw new IllegalStateException("Connection was not established (JDBC driver returned null value)."); + + return conn; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbTable.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbTable.java b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbTable.java new file mode 100644 index 0000000..39f6f7b --- /dev/null +++ b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/DbTable.java @@ -0,0 +1,82 @@ +/* + * 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.apache.ignite.schema.parser; + +import org.apache.ignite.cache.QueryIndex; + +import java.util.Collection; + +/** + * Database table. + */ +public class DbTable { + /** Schema name. */ + private final String schema; + + /** Table name. */ + private final String tbl; + + /** Columns. */ + private final Collection<DbColumn> cols; + + /** Indexes. */ + private final Collection<QueryIndex> idxs; + + /** + * Default columns. + * + * @param schema Schema name. + * @param tbl Table name. + * @param cols Columns. + * @param idxs Indexes; + */ + public DbTable(String schema, String tbl, Collection<DbColumn> cols, Collection<QueryIndex> idxs) { + this.schema = schema; + this.tbl = tbl; + this.cols = cols; + this.idxs = idxs; + } + + /** + * @return Schema name. + */ + public String schema() { + return schema; + } + + /** + * @return Table name. + */ + public String table() { + return tbl; + } + + /** + * @return Columns. + */ + public Collection<DbColumn> columns() { + return cols; + } + + /** + * @return Indexes. + */ + public Collection<QueryIndex> indexes() { + return idxs; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/DB2MetadataDialect.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/DB2MetadataDialect.java b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/DB2MetadataDialect.java new file mode 100644 index 0000000..b191ec3 --- /dev/null +++ b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/DB2MetadataDialect.java @@ -0,0 +1,33 @@ +/* + * 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.apache.ignite.schema.parser.dialect; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * DB2 specific metadata dialect. + */ +public class DB2MetadataDialect extends JdbcMetadataDialect { + /** {@inheritDoc} */ + @Override public Set<String> systemSchemas() { + return new HashSet<>(Arrays.asList("SYSIBM", "SYSCAT", "SYSSTAT", "SYSTOOLS", "SYSFUN", "SYSIBMADM", + "SYSIBMINTERNAL", "SYSIBMTS", "SYSPROC", "SYSPUBLIC")); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java new file mode 100644 index 0000000..f34eee4 --- /dev/null +++ b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java @@ -0,0 +1,75 @@ +/* + * 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.apache.ignite.schema.parser.dialect; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.apache.ignite.cache.QueryIndex; +import org.apache.ignite.schema.parser.DbColumn; +import org.apache.ignite.schema.parser.DbTable; + +/** + * Base class for database metadata dialect. + */ +public abstract class DatabaseMetadataDialect { + /** + * Gets schemas from database. + * + * @param conn Database connection. + * @return Collection of schema descriptors. + * @throws SQLException If failed to get schemas. + */ + public abstract Collection<String> schemas(Connection conn) throws SQLException; + + /** + * Gets tables from database. + * + * @param conn Database connection. + * @param schemas Collection of schema names to load. + * @param tblsOnly If {@code true} then gets only tables otherwise gets tables and views. + * @return Collection of table descriptors. + * @throws SQLException If failed to get tables. + */ + public abstract Collection<DbTable> tables(Connection conn, List<String> schemas, boolean tblsOnly) + throws SQLException; + + /** + * @return Collection of database system schemas. + */ + public Set<String> systemSchemas() { + return Collections.singleton("INFORMATION_SCHEMA"); + } + + /** + * Create table descriptor. + * + * @param schema Schema name. + * @param tbl Table name. + * @param cols Table columns. + * @param idxs Table indexes. + * @return New {@code DbTable} instance. + */ + protected DbTable table(String schema, String tbl, Collection<DbColumn> cols, Collection<QueryIndex>idxs) { + return new DbTable(schema, tbl, cols, idxs); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java new file mode 100644 index 0000000..0b54b25 --- /dev/null +++ b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java @@ -0,0 +1,197 @@ +/* + * 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.apache.ignite.schema.parser.dialect; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.ignite.cache.QueryIndex; +import org.apache.ignite.cache.QueryIndexType; +import org.apache.ignite.schema.parser.DbColumn; +import org.apache.ignite.schema.parser.DbTable; + +/** + * Metadata dialect that uses standard JDBC for reading metadata. + */ +public class JdbcMetadataDialect extends DatabaseMetadataDialect { + /** */ + private static final String[] TABLES_ONLY = {"TABLE"}; + + /** */ + private static final String[] TABLES_AND_VIEWS = {"TABLE", "VIEW"}; + + /** Schema catalog index. */ + private static final int TBL_CATALOG_IDX = 1; + + /** Schema name index. */ + private static final int TBL_SCHEMA_IDX = 2; + + /** Table name index. */ + private static final int TBL_NAME_IDX = 3; + + /** Primary key column name index. */ + private static final int PK_COL_NAME_IDX = 4; + + /** Column name index. */ + private static final int COL_NAME_IDX = 4; + + /** Column data type index. */ + private static final int COL_DATA_TYPE_IDX = 5; + + /** Column nullable index. */ + private static final int COL_NULLABLE_IDX = 11; + + /** Index name index. */ + private static final int IDX_NAME_IDX = 6; + + /** Index column name index. */ + private static final int IDX_COL_NAME_IDX = 9; + + /** Index column descend index. */ + private static final int IDX_ASC_OR_DESC_IDX = 10; + + /** {@inheritDoc} */ + @Override public Collection<String> schemas(Connection conn) throws SQLException { + Collection<String> schemas = new ArrayList<>(); + + ResultSet rs = conn.getMetaData().getSchemas(); + + Set<String> sys = systemSchemas(); + + while(rs.next()) { + String schema = rs.getString(1); + + // Skip system schemas. + if (sys.contains(schema)) + continue; + + schemas.add(schema); + } + + return schemas; + } + + /** + * @return If {@code true} use catalogs for table division. + */ + protected boolean useCatalog() { + return false; + } + + /** + * @return If {@code true} use schemas for table division. + */ + protected boolean useSchema() { + return true; + } + + /** {@inheritDoc} */ + @Override public Collection<DbTable> tables(Connection conn, List<String> schemas, boolean tblsOnly) + throws SQLException { + DatabaseMetaData dbMeta = conn.getMetaData(); + + Set<String> sys = systemSchemas(); + + Collection<DbTable> tbls = new ArrayList<>(); + + if (schemas.isEmpty()) + schemas.add(null); + + for (String toSchema: schemas) { + try (ResultSet tblsRs = dbMeta.getTables(useCatalog() ? toSchema : null, useSchema() ? toSchema : null, "%", + tblsOnly ? TABLES_ONLY : TABLES_AND_VIEWS)) { + while (tblsRs.next()) { + String tblCatalog = tblsRs.getString(TBL_CATALOG_IDX); + String tblSchema = tblsRs.getString(TBL_SCHEMA_IDX); + String tblName = tblsRs.getString(TBL_NAME_IDX); + + // In case of MySql we should use catalog. + String schema = tblSchema != null ? tblSchema : tblCatalog; + + // Skip system schemas. + if (sys.contains(schema)) + continue; + + Set<String> pkCols = new HashSet<>(); + + try (ResultSet pkRs = dbMeta.getPrimaryKeys(tblCatalog, tblSchema, tblName)) { + while (pkRs.next()) + pkCols.add(pkRs.getString(PK_COL_NAME_IDX)); + } + + List<DbColumn> cols = new ArrayList<>(); + + try (ResultSet colsRs = dbMeta.getColumns(tblCatalog, tblSchema, tblName, null)) { + while (colsRs.next()) { + String colName = colsRs.getString(COL_NAME_IDX); + + cols.add(new DbColumn( + colName, + colsRs.getInt(COL_DATA_TYPE_IDX), + pkCols.contains(colName), + colsRs.getInt(COL_NULLABLE_IDX) == DatabaseMetaData.columnNullable)); + } + } + + Map<String, QueryIndex> idxs = new LinkedHashMap<>(); + + try (ResultSet idxRs = dbMeta.getIndexInfo(tblCatalog, tblSchema, tblName, false, true)) { + while (idxRs.next()) { + String idxName = idxRs.getString(IDX_NAME_IDX); + + String colName = idxRs.getString(IDX_COL_NAME_IDX); + + if (idxName == null || colName == null) + continue; + + QueryIndex idx = idxs.get(idxName); + + if (idx == null) { + idx = new QueryIndex(); + idx.setName(idxName); + idx.setIndexType(QueryIndexType.SORTED); + idx.setFields(new LinkedHashMap<String, Boolean>()); + + idxs.put(idxName, idx); + } + + String askOrDesc = idxRs.getString(IDX_ASC_OR_DESC_IDX); + + Boolean asc = askOrDesc == null || "A".equals(askOrDesc); + + idx.getFields().put(colName, asc); + } + } + + tbls.add(table(schema, tblName, cols, idxs.values())); + } + } + } + + return tbls; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/MySQLMetadataDialect.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/MySQLMetadataDialect.java b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/MySQLMetadataDialect.java new file mode 100644 index 0000000..3332046 --- /dev/null +++ b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/MySQLMetadataDialect.java @@ -0,0 +1,62 @@ +/* + * 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.apache.ignite.schema.parser.dialect; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + * MySQL specific metadata dialect. + */ +public class MySQLMetadataDialect extends JdbcMetadataDialect { + /** {@inheritDoc} */ + @Override public Collection<String> schemas(Connection conn) throws SQLException { + List<String> schemas = new ArrayList<>(); + + ResultSet rs = conn.getMetaData().getCatalogs(); + + Set<String> sys = systemSchemas(); + + while(rs.next()) { + String schema = rs.getString(1); + + // Skip system schemas. + if (sys.contains(schema)) + continue; + + schemas.add(schema); + } + + return schemas; + } + + /** {@inheritDoc} */ + @Override protected boolean useCatalog() { + return true; + } + + /** {@inheritDoc} */ + @Override protected boolean useSchema() { + return false; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java new file mode 100644 index 0000000..ed5cdc5 --- /dev/null +++ b/modules/schema-import-db/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java @@ -0,0 +1,364 @@ +/* + * 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.apache.ignite.schema.parser.dialect; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.ignite.cache.QueryIndex; +import org.apache.ignite.cache.QueryIndexType; +import org.apache.ignite.schema.parser.DbColumn; +import org.apache.ignite.schema.parser.DbTable; + +import static java.sql.Types.BIGINT; +import static java.sql.Types.BLOB; +import static java.sql.Types.BOOLEAN; +import static java.sql.Types.CHAR; +import static java.sql.Types.CLOB; +import static java.sql.Types.DATE; +import static java.sql.Types.DOUBLE; +import static java.sql.Types.FLOAT; +import static java.sql.Types.INTEGER; +import static java.sql.Types.LONGVARBINARY; +import static java.sql.Types.LONGVARCHAR; +import static java.sql.Types.NUMERIC; +import static java.sql.Types.OTHER; +import static java.sql.Types.SMALLINT; +import static java.sql.Types.SQLXML; +import static java.sql.Types.TIMESTAMP; +import static java.sql.Types.TINYINT; +import static java.sql.Types.VARCHAR; + +/** + * Oracle specific metadata dialect. + */ +public class OracleMetadataDialect extends DatabaseMetadataDialect { + /** SQL to get columns metadata. */ + private static final String SQL_COLUMNS = "SELECT a.owner, a.table_name, a.column_name, a.nullable," + + " a.data_type, a.data_precision, a.data_scale " + + "FROM all_tab_columns a %s " + + " %s " + + " ORDER BY a.owner, a.table_name, a.column_id"; + + /** SQL to get list of PRIMARY KEYS columns. */ + private static final String SQL_PRIMARY_KEYS = "SELECT b.column_name" + + " FROM all_constraints a" + + " INNER JOIN all_cons_columns b ON a.owner = b.owner AND a.constraint_name = b.constraint_name" + + " WHERE a.owner = ? and a.table_name = ? AND a.constraint_type = 'P'"; + + /** SQL to get indexes metadata. */ + private static final String SQL_INDEXES = "SELECT i.index_name, u.column_expression, i.column_name, i.descend" + + " FROM all_ind_columns i" + + " LEFT JOIN user_ind_expressions u on u.index_name = i.index_name and i.table_name = u.table_name" + + " WHERE i.index_owner = ? and i.table_name = ?" + + " ORDER BY i.index_name, i.column_position"; + + /** Owner index. */ + private static final int OWNER_IDX = 1; + + /** Table name index. */ + private static final int TBL_NAME_IDX = 2; + + /** Column name index. */ + private static final int COL_NAME_IDX = 3; + + /** Nullable index. */ + private static final int NULLABLE_IDX = 4; + + /** Data type index. */ + private static final int DATA_TYPE_IDX = 5; + + /** Numeric precision index. */ + private static final int DATA_PRECISION_IDX = 6; + + /** Numeric scale index. */ + private static final int DATA_SCALE_IDX = 7; + + /** Index name index. */ + private static final int IDX_NAME_IDX = 1; + + /** Index name index. */ + private static final int IDX_EXPR_IDX = 2; + + /** Index column name index. */ + private static final int IDX_COL_NAME_IDX = 3; + + /** Index column sort order index. */ + private static final int IDX_COL_DESCEND_IDX = 4; + + /** {@inheritDoc} */ + @Override public Set<String> systemSchemas() { + return new HashSet<>(Arrays.asList("ANONYMOUS", "CTXSYS", "DBSNMP", "EXFSYS", "LBACSYS", "MDSYS", "MGMT_VIEW", + "OLAPSYS", "OWBSYS", "ORDPLUGINS", "ORDSYS", "OUTLN", "SI_INFORMTN_SCHEMA", "SYS", "SYSMAN", "SYSTEM", + "TSMSYS", "WK_TEST", "WKSYS", "WKPROXY", "WMSYS", "XDB", + + "APEX_040000", "APEX_PUBLIC_USER", "DIP", "FLOWS_30000", "FLOWS_FILES", "MDDATA", "ORACLE_OCM", + "SPATIAL_CSW_ADMIN_USR", "SPATIAL_WFS_ADMIN_USR", "XS$NULL", + + "BI", "HR", "OE", "PM", "IX", "SH")); + } + + /** {@inheritDoc} */ + @Override public Collection<String> schemas(Connection conn) throws SQLException { + Collection<String> schemas = new ArrayList<>(); + + ResultSet rs = conn.getMetaData().getSchemas(); + + Set<String> sysSchemas = systemSchemas(); + + while(rs.next()) { + String schema = rs.getString(1); + + if (!sysSchemas.contains(schema) && !schema.startsWith("FLOWS_")) + schemas.add(schema); + } + + return schemas; + } + + /** + * @param rs Result set with column type metadata from Oracle database. + * @return JDBC type. + * @throws SQLException If failed to decode type. + */ + private int decodeType(ResultSet rs) throws SQLException { + String type = rs.getString(DATA_TYPE_IDX); + + if (type.startsWith("TIMESTAMP")) + return TIMESTAMP; + else { + switch (type) { + case "CHAR": + case "NCHAR": + return CHAR; + + case "VARCHAR2": + case "NVARCHAR2": + return VARCHAR; + + case "LONG": + return LONGVARCHAR; + + case "LONG RAW": + return LONGVARBINARY; + + case "FLOAT": + return FLOAT; + + case "NUMBER": + int precision = rs.getInt(DATA_PRECISION_IDX); + int scale = rs.getInt(DATA_SCALE_IDX); + + if (scale > 0) { + if (scale < 4 && precision < 19) + return FLOAT; + + if (scale > 4 || precision > 19) + return DOUBLE; + + return NUMERIC; + } + else { + if (precision < 1) + return INTEGER; + + if (precision < 2) + return BOOLEAN; + + if (precision < 4) + return TINYINT; + + if (precision < 6) + return SMALLINT; + + if (precision < 11) + return INTEGER; + + if (precision < 20) + return BIGINT; + + return NUMERIC; + } + + case "DATE": + return DATE; + + case "BFILE": + case "BLOB": + return BLOB; + + case "CLOB": + case "NCLOB": + return CLOB; + + case "XMLTYPE": + return SQLXML; + } + } + + return OTHER; + } + + /** + * Retrieve primary key columns. + * + * @param stmt Prepared SQL statement to execute. + * @param owner DB owner. + * @param tbl Table name. + * @return Primary key columns. + * @throws SQLException If failed to retrieve primary key columns. + */ + private Set<String> primaryKeys(PreparedStatement stmt, String owner, String tbl) throws SQLException { + Set<String> pkCols = new HashSet<>(); + + stmt.setString(1, owner); + stmt.setString(2, tbl); + + try (ResultSet pkRs = stmt.executeQuery()) { + while(pkRs.next()) + pkCols.add(pkRs.getString(1)); + } + + return pkCols; + } + + /** + * Retrieve index columns. + * + * @param stmt Prepared SQL statement to execute. + * @param owner DB owner. + * @param tbl Table name. + * @return Indexes. + * @throws SQLException If failed to retrieve indexes columns. + */ + private Collection<QueryIndex> indexes(PreparedStatement stmt, String owner, String tbl) + throws SQLException { + Map<String, QueryIndex> idxs = new LinkedHashMap<>(); + + stmt.setString(1, owner); + stmt.setString(2, tbl); + + try (ResultSet idxsRs = stmt.executeQuery()) { + while (idxsRs.next()) { + String idxName = idxsRs.getString(IDX_NAME_IDX); + + QueryIndex idx = idxs.get(idxName); + + if (idx == null) { + idx = new QueryIndex(); + idx.setName(idxName); + idx.setIndexType(QueryIndexType.SORTED); + idx.setFields(new LinkedHashMap<String, Boolean>()); + + idxs.put(idxName, idx); + } + + String expr = idxsRs.getString(IDX_EXPR_IDX); + + String col = expr == null ? idxsRs.getString(IDX_COL_NAME_IDX) : expr.replaceAll("\"", ""); + + idx.getFields().put(col, !"DESC".equals(idxsRs.getString(IDX_COL_DESCEND_IDX))); + } + } + + return idxs.values(); + } + + /** {@inheritDoc} */ + @Override public Collection<DbTable> tables(Connection conn, List<String> schemas, boolean tblsOnly) + throws SQLException { + Collection<DbTable> tbls = new ArrayList<>(); + + PreparedStatement pkStmt = conn.prepareStatement(SQL_PRIMARY_KEYS); + + PreparedStatement idxStmt = conn.prepareStatement(SQL_INDEXES); + + if (schemas.isEmpty()) + schemas.add(null); + + Set<String> sysSchemas = systemSchemas(); + + try (Statement colsStmt = conn.createStatement()) { + for (String schema: schemas) { + if (systemSchemas().contains(schema) || (schema != null && schema.startsWith("FLOWS_"))) + continue; + + Collection<DbColumn> cols = new ArrayList<>(); + + Set<String> pkCols = Collections.emptySet(); + Collection<QueryIndex> idxs = Collections.emptyList(); + + String sql = String.format(SQL_COLUMNS, + tblsOnly ? "INNER JOIN all_tables b on a.table_name = b.table_name and a.owner = b.owner" : "", + schema != null ? String.format(" WHERE a.owner = '%s' ", schema) : ""); + + try (ResultSet colsRs = colsStmt.executeQuery(sql)) { + String prevSchema = ""; + String prevTbl = ""; + + boolean first = true; + + while (colsRs.next()) { + String owner = colsRs.getString(OWNER_IDX); + String tbl = colsRs.getString(TBL_NAME_IDX); + + if (sysSchemas.contains(owner) || (schema != null && schema.startsWith("FLOWS_"))) + continue; + + boolean changed = !owner.equals(prevSchema) || !tbl.equals(prevTbl); + + if (changed) { + if (first) + first = false; + else + tbls.add(table(prevSchema, prevTbl, cols, idxs)); + + prevSchema = owner; + prevTbl = tbl; + cols = new ArrayList<>(); + pkCols = primaryKeys(pkStmt, owner, tbl); + idxs = indexes(idxStmt, owner, tbl); + } + + String colName = colsRs.getString(COL_NAME_IDX); + + cols.add(new DbColumn(colName, decodeType(colsRs), pkCols.contains(colName), + !"N".equals(colsRs.getString(NULLABLE_IDX)))); + } + + if (!cols.isEmpty()) + tbls.add(table(prevSchema, prevTbl, cols, idxs)); + } + } + } + + return tbls; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import/pom.xml ---------------------------------------------------------------------- diff --git a/modules/schema-import/pom.xml b/modules/schema-import/pom.xml index 7156e32..7e83a84 100644 --- a/modules/schema-import/pom.xml +++ b/modules/schema-import/pom.xml @@ -42,6 +42,12 @@ </dependency> <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-schema-import-db</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>${h2.version}</version> http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java ---------------------------------------------------------------------- diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java index c4490ef..b86346f 100644 --- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java +++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java @@ -26,52 +26,16 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import org.apache.ignite.cache.QueryIndex; import org.apache.ignite.schema.model.PojoDescriptor; import org.apache.ignite.schema.model.SchemaDescriptor; -import org.apache.ignite.schema.parser.dialect.DB2MetadataDialect; -import org.apache.ignite.schema.parser.dialect.DatabaseMetadataDialect; -import org.apache.ignite.schema.parser.dialect.JdbcMetadataDialect; -import org.apache.ignite.schema.parser.dialect.MySQLMetadataDialect; -import org.apache.ignite.schema.parser.dialect.OracleMetadataDialect; /** * Database metadata parser. */ public class DatabaseMetadataParser { - /** Logger. */ - private static final Logger log = Logger.getLogger(DatabaseMetadataParser.class.getName()); - - /** - * Get specified dialect object for selected database. - * - * @param conn Connection to database. - * @return Specific dialect object. - */ - private static DatabaseMetadataDialect dialect(Connection conn) { - try { - String dbProductName = conn.getMetaData().getDatabaseProductName(); - - if ("Oracle".equals(dbProductName)) - return new OracleMetadataDialect(); - else if (dbProductName.startsWith("DB2/")) - return new DB2MetadataDialect(); - else if ("MySQL".equals(dbProductName)) - return new MySQLMetadataDialect(); - else - return new JdbcMetadataDialect(); - } - catch (SQLException e) { - log.log(Level.SEVERE, "Failed to resolve dialect (JdbcMetaDataDialect will be used.", e); - - return new JdbcMetadataDialect(); - } - } - /** * Get list of schemas from database. * @@ -80,7 +44,7 @@ public class DatabaseMetadataParser { * @throws SQLException If schemas loading failed. */ public static ObservableList<SchemaDescriptor> schemas(Connection conn) throws SQLException { - List<String> dbSchemas = dialect(conn).schemas(conn); + Collection<String> dbSchemas = DbMetadataReader.getInstance().schemas(conn); List<SchemaDescriptor> uiSchemas = new ArrayList<>(dbSchemas.size()); @@ -94,20 +58,18 @@ public class DatabaseMetadataParser { * Parse database metadata. * * @param conn Connection to database. - * @param schemas Collection of schema names to load. + * @param schemas Collection of schema names to process. * @param tblsOnly If {@code true} then process tables only else process tables and views. * @return Collection of POJO descriptors. * @throws SQLException If parsing failed. */ public static ObservableList<PojoDescriptor> parse(Connection conn, List<String> schemas, boolean tblsOnly) throws SQLException { - DatabaseMetadataDialect dialect = dialect(conn); - Map<String, PojoDescriptor> parents = new HashMap<>(); Map<String, Collection<PojoDescriptor>> childrens = new HashMap<>(); - for (DbTable tbl : dialect.tables(conn, schemas, tblsOnly)) { + for (DbTable tbl : DbMetadataReader.getInstance().metadata(conn, schemas, tblsOnly)) { String schema = tbl.schema(); PojoDescriptor parent = parents.get(schema); http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbColumn.java ---------------------------------------------------------------------- diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbColumn.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbColumn.java deleted file mode 100644 index 9a548f4..0000000 --- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbColumn.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.apache.ignite.schema.parser; - -/** - * Database table column. - */ -public class DbColumn { - /** Column name. */ - private final String name; - - /** Column JDBC type. */ - private final int type; - - /** Is this column belongs to primary key. */ - private final boolean key; - - /** Is {@code NULL} allowed for column in database. */ - private final boolean nullable; - - /** - * @param name Column name. - * @param type Column JDBC type. - * @param key {@code true} if this column belongs to primary key. - * @param nullable {@code true} if {@code NULL } allowed for column in database. - */ - public DbColumn(String name, int type, boolean key, boolean nullable) { - this.name = name; - this.type = type; - this.key = key; - this.nullable = nullable; - } - - /** - * @return Column name. - */ - public String name() { - return name; - } - - /** - * @return Column JDBC type. - */ - public int type() { - return type; - } - - /** - * @return {@code true} if this column belongs to primary key. - */ - public boolean key() { - return key; - } - - /** - * @return nullable {@code true} if {@code NULL } allowed for column in database. - */ - public boolean nullable() { - return nullable; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbTable.java ---------------------------------------------------------------------- diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbTable.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbTable.java deleted file mode 100644 index 39f6f7b..0000000 --- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbTable.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.apache.ignite.schema.parser; - -import org.apache.ignite.cache.QueryIndex; - -import java.util.Collection; - -/** - * Database table. - */ -public class DbTable { - /** Schema name. */ - private final String schema; - - /** Table name. */ - private final String tbl; - - /** Columns. */ - private final Collection<DbColumn> cols; - - /** Indexes. */ - private final Collection<QueryIndex> idxs; - - /** - * Default columns. - * - * @param schema Schema name. - * @param tbl Table name. - * @param cols Columns. - * @param idxs Indexes; - */ - public DbTable(String schema, String tbl, Collection<DbColumn> cols, Collection<QueryIndex> idxs) { - this.schema = schema; - this.tbl = tbl; - this.cols = cols; - this.idxs = idxs; - } - - /** - * @return Schema name. - */ - public String schema() { - return schema; - } - - /** - * @return Table name. - */ - public String table() { - return tbl; - } - - /** - * @return Columns. - */ - public Collection<DbColumn> columns() { - return cols; - } - - /** - * @return Indexes. - */ - public Collection<QueryIndex> indexes() { - return idxs; - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DB2MetadataDialect.java ---------------------------------------------------------------------- diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DB2MetadataDialect.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DB2MetadataDialect.java deleted file mode 100644 index b191ec3..0000000 --- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DB2MetadataDialect.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.apache.ignite.schema.parser.dialect; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -/** - * DB2 specific metadata dialect. - */ -public class DB2MetadataDialect extends JdbcMetadataDialect { - /** {@inheritDoc} */ - @Override public Set<String> systemSchemas() { - return new HashSet<>(Arrays.asList("SYSIBM", "SYSCAT", "SYSSTAT", "SYSTOOLS", "SYSFUN", "SYSIBMADM", - "SYSIBMINTERNAL", "SYSIBMTS", "SYSPROC", "SYSPUBLIC")); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java ---------------------------------------------------------------------- diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java deleted file mode 100644 index bdf309b..0000000 --- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.apache.ignite.schema.parser.dialect; - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import org.apache.ignite.cache.QueryIndex; -import org.apache.ignite.schema.parser.DbColumn; -import org.apache.ignite.schema.parser.DbTable; - -/** - * Base class for database metadata dialect. - */ -public abstract class DatabaseMetadataDialect { - /** - * Gets schemas from database. - * - * @param conn Database connection. - * @return Collection of schema descriptors. - * @throws SQLException If failed to get schemas. - */ - public abstract List<String> schemas(Connection conn) throws SQLException; - - /** - * Gets tables from database. - * - * @param conn Database connection. - * @param schemas Collection of schema names to load. - * @param tblsOnly If {@code true} then gets only tables otherwise gets tables and views. - * @return Collection of table descriptors. - * @throws SQLException If failed to get tables. - */ - public abstract Collection<DbTable> tables(Connection conn, List<String> schemas, boolean tblsOnly) - throws SQLException; - - /** - * @return Collection of database system schemas. - */ - public Set<String> systemSchemas() { - return Collections.singleton("INFORMATION_SCHEMA"); - } - - /** - * Create table descriptor. - * - * @param schema Schema name. - * @param tbl Table name. - * @param cols Table columns. - * @param idxs Table indexes. - * @return New {@code DbTable} instance. - */ - protected DbTable table(String schema, String tbl, Collection<DbColumn> cols, Collection<QueryIndex>idxs) { - return new DbTable(schema, tbl, cols, idxs); - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java ---------------------------------------------------------------------- diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java deleted file mode 100644 index 45f0f9f..0000000 --- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * 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.apache.ignite.schema.parser.dialect; - -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.ignite.cache.QueryIndex; -import org.apache.ignite.cache.QueryIndexType; -import org.apache.ignite.schema.parser.DbColumn; -import org.apache.ignite.schema.parser.DbTable; - -/** - * Metadata dialect that uses standard JDBC for reading metadata. - */ -public class JdbcMetadataDialect extends DatabaseMetadataDialect { - /** */ - private static final String[] TABLES_ONLY = {"TABLE"}; - - /** */ - private static final String[] TABLES_AND_VIEWS = {"TABLE", "VIEW"}; - - /** Schema catalog index. */ - private static final int TBL_CATALOG_IDX = 1; - - /** Schema name index. */ - private static final int TBL_SCHEMA_IDX = 2; - - /** Table name index. */ - private static final int TBL_NAME_IDX = 3; - - /** Primary key column name index. */ - private static final int PK_COL_NAME_IDX = 4; - - /** Column name index. */ - private static final int COL_NAME_IDX = 4; - - /** Column data type index. */ - private static final int COL_DATA_TYPE_IDX = 5; - - /** Column nullable index. */ - private static final int COL_NULLABLE_IDX = 11; - - /** Index name index. */ - private static final int IDX_NAME_IDX = 6; - - /** Index column name index. */ - private static final int IDX_COL_NAME_IDX = 9; - - /** Index column descend index. */ - private static final int IDX_ASC_OR_DESC_IDX = 10; - - /** {@inheritDoc} */ - @Override public List<String> schemas(Connection conn) throws SQLException { - List<String> schemas = new ArrayList<>(); - - ResultSet rs = conn.getMetaData().getSchemas(); - - Set<String> sys = systemSchemas(); - - while(rs.next()) { - String schema = rs.getString(1); - - // Skip system schemas. - if (sys.contains(schema)) - continue; - - schemas.add(schema); - } - - return schemas; - } - - /** - * @return If {@code true} use catalogs for table division. - */ - protected boolean useCatalog() { - return false; - } - - /** - * @return If {@code true} use schemas for table division. - */ - protected boolean useSchema() { - return true; - } - - /** {@inheritDoc} */ - @Override public Collection<DbTable> tables(Connection conn, List<String> schemas, boolean tblsOnly) - throws SQLException { - DatabaseMetaData dbMeta = conn.getMetaData(); - - Set<String> sys = systemSchemas(); - - Collection<DbTable> tbls = new ArrayList<>(); - - if (schemas.isEmpty()) - schemas.add(null); - - for (String toSchema: schemas) { - try (ResultSet tblsRs = dbMeta.getTables(useCatalog() ? toSchema : null, useSchema() ? toSchema : null, "%", - tblsOnly ? TABLES_ONLY : TABLES_AND_VIEWS)) { - while (tblsRs.next()) { - String tblCatalog = tblsRs.getString(TBL_CATALOG_IDX); - String tblSchema = tblsRs.getString(TBL_SCHEMA_IDX); - String tblName = tblsRs.getString(TBL_NAME_IDX); - - // In case of MySql we should use catalog. - String schema = tblSchema != null ? tblSchema : tblCatalog; - - // Skip system schemas. - if (sys.contains(schema)) - continue; - - Set<String> pkCols = new HashSet<>(); - - try (ResultSet pkRs = dbMeta.getPrimaryKeys(tblCatalog, tblSchema, tblName)) { - while (pkRs.next()) - pkCols.add(pkRs.getString(PK_COL_NAME_IDX)); - } - - List<DbColumn> cols = new ArrayList<>(); - - try (ResultSet colsRs = dbMeta.getColumns(tblCatalog, tblSchema, tblName, null)) { - while (colsRs.next()) { - String colName = colsRs.getString(COL_NAME_IDX); - - cols.add(new DbColumn( - colName, - colsRs.getInt(COL_DATA_TYPE_IDX), - pkCols.contains(colName), - colsRs.getInt(COL_NULLABLE_IDX) == DatabaseMetaData.columnNullable)); - } - } - - Map<String, QueryIndex> idxs = new LinkedHashMap<>(); - - try (ResultSet idxRs = dbMeta.getIndexInfo(tblCatalog, tblSchema, tblName, false, true)) { - while (idxRs.next()) { - String idxName = idxRs.getString(IDX_NAME_IDX); - - String colName = idxRs.getString(IDX_COL_NAME_IDX); - - if (idxName == null || colName == null) - continue; - - QueryIndex idx = idxs.get(idxName); - - if (idx == null) { - idx = new QueryIndex(); - idx.setName(idxName); - idx.setIndexType(QueryIndexType.SORTED); - idx.setFields(new LinkedHashMap<String, Boolean>()); - - idxs.put(idxName, idx); - } - - String askOrDesc = idxRs.getString(IDX_ASC_OR_DESC_IDX); - - Boolean asc = askOrDesc == null || "A".equals(askOrDesc); - - idx.getFields().put(colName, asc); - } - } - - tbls.add(table(schema, tblName, cols, idxs.values())); - } - } - } - - return tbls; - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/MySQLMetadataDialect.java ---------------------------------------------------------------------- diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/MySQLMetadataDialect.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/MySQLMetadataDialect.java deleted file mode 100644 index 090925e..0000000 --- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/MySQLMetadataDialect.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.apache.ignite.schema.parser.dialect; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -/** - * MySQL specific metadata dialect. - */ -public class MySQLMetadataDialect extends JdbcMetadataDialect { - /** {@inheritDoc} */ - @Override public List<String> schemas(Connection conn) throws SQLException { - List<String> schemas = new ArrayList<>(); - - ResultSet rs = conn.getMetaData().getCatalogs(); - - Set<String> sys = systemSchemas(); - - while(rs.next()) { - String schema = rs.getString(1); - - // Skip system schemas. - if (sys.contains(schema)) - continue; - - schemas.add(schema); - } - - return schemas; - } - - /** {@inheritDoc} */ - @Override protected boolean useCatalog() { - return true; - } - - /** {@inheritDoc} */ - @Override protected boolean useSchema() { - return false; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/fa197d2f/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java ---------------------------------------------------------------------- diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java deleted file mode 100644 index 0d4e8d6..0000000 --- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * 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.apache.ignite.schema.parser.dialect; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.ignite.cache.QueryIndex; -import org.apache.ignite.cache.QueryIndexType; -import org.apache.ignite.schema.parser.DbColumn; -import org.apache.ignite.schema.parser.DbTable; - -import static java.sql.Types.BIGINT; -import static java.sql.Types.BLOB; -import static java.sql.Types.BOOLEAN; -import static java.sql.Types.CHAR; -import static java.sql.Types.CLOB; -import static java.sql.Types.DATE; -import static java.sql.Types.DOUBLE; -import static java.sql.Types.FLOAT; -import static java.sql.Types.INTEGER; -import static java.sql.Types.LONGVARBINARY; -import static java.sql.Types.LONGVARCHAR; -import static java.sql.Types.NUMERIC; -import static java.sql.Types.OTHER; -import static java.sql.Types.SMALLINT; -import static java.sql.Types.SQLXML; -import static java.sql.Types.TIMESTAMP; -import static java.sql.Types.TINYINT; -import static java.sql.Types.VARCHAR; - -/** - * Oracle specific metadata dialect. - */ -public class OracleMetadataDialect extends DatabaseMetadataDialect { - /** SQL to get columns metadata. */ - private static final String SQL_COLUMNS = "SELECT a.owner, a.table_name, a.column_name, a.nullable," + - " a.data_type, a.data_precision, a.data_scale " + - "FROM all_tab_columns a %s " + - " %s " + - " ORDER BY a.owner, a.table_name, a.column_id"; - - /** SQL to get list of PRIMARY KEYS columns. */ - private static final String SQL_PRIMARY_KEYS = "SELECT b.column_name" + - " FROM all_constraints a" + - " INNER JOIN all_cons_columns b ON a.owner = b.owner AND a.constraint_name = b.constraint_name" + - " WHERE a.owner = ? and a.table_name = ? AND a.constraint_type = 'P'"; - - /** SQL to get indexes metadata. */ - private static final String SQL_INDEXES = "SELECT i.index_name, u.column_expression, i.column_name, i.descend" + - " FROM all_ind_columns i" + - " LEFT JOIN user_ind_expressions u on u.index_name = i.index_name and i.table_name = u.table_name" + - " WHERE i.index_owner = ? and i.table_name = ?" + - " ORDER BY i.index_name, i.column_position"; - - /** Owner index. */ - private static final int OWNER_IDX = 1; - - /** Table name index. */ - private static final int TBL_NAME_IDX = 2; - - /** Column name index. */ - private static final int COL_NAME_IDX = 3; - - /** Nullable index. */ - private static final int NULLABLE_IDX = 4; - - /** Data type index. */ - private static final int DATA_TYPE_IDX = 5; - - /** Numeric precision index. */ - private static final int DATA_PRECISION_IDX = 6; - - /** Numeric scale index. */ - private static final int DATA_SCALE_IDX = 7; - - /** Index name index. */ - private static final int IDX_NAME_IDX = 1; - - /** Index name index. */ - private static final int IDX_EXPR_IDX = 2; - - /** Index column name index. */ - private static final int IDX_COL_NAME_IDX = 3; - - /** Index column sort order index. */ - private static final int IDX_COL_DESCEND_IDX = 4; - - /** {@inheritDoc} */ - @Override public Set<String> systemSchemas() { - return new HashSet<>(Arrays.asList("ANONYMOUS", "CTXSYS", "DBSNMP", "EXFSYS", "LBACSYS", "MDSYS", "MGMT_VIEW", - "OLAPSYS", "OWBSYS", "ORDPLUGINS", "ORDSYS", "OUTLN", "SI_INFORMTN_SCHEMA", "SYS", "SYSMAN", "SYSTEM", - "TSMSYS", "WK_TEST", "WKSYS", "WKPROXY", "WMSYS", "XDB", - - "APEX_040000", "APEX_PUBLIC_USER", "DIP", "FLOWS_30000", "FLOWS_FILES", "MDDATA", "ORACLE_OCM", - "SPATIAL_CSW_ADMIN_USR", "SPATIAL_WFS_ADMIN_USR", "XS$NULL", - - "BI", "HR", "OE", "PM", "IX", "SH")); - } - - /** {@inheritDoc} */ - @Override public List<String> schemas(Connection conn) throws SQLException { - List<String> schemas = new ArrayList<>(); - - ResultSet rs = conn.getMetaData().getSchemas(); - - Set<String> sysSchemas = systemSchemas(); - - while(rs.next()) { - String schema = rs.getString(1); - - if (!sysSchemas.contains(schema) && !schema.startsWith("FLOWS_")) - schemas.add(schema); - } - - return schemas; - } - - /** - * @param rs Result set with column type metadata from Oracle database. - * @return JDBC type. - * @throws SQLException If failed to decode type. - */ - private int decodeType(ResultSet rs) throws SQLException { - String type = rs.getString(DATA_TYPE_IDX); - - if (type.startsWith("TIMESTAMP")) - return TIMESTAMP; - else { - switch (type) { - case "CHAR": - case "NCHAR": - return CHAR; - - case "VARCHAR2": - case "NVARCHAR2": - return VARCHAR; - - case "LONG": - return LONGVARCHAR; - - case "LONG RAW": - return LONGVARBINARY; - - case "FLOAT": - return FLOAT; - - case "NUMBER": - int precision = rs.getInt(DATA_PRECISION_IDX); - int scale = rs.getInt(DATA_SCALE_IDX); - - if (scale > 0) { - if (scale < 4 && precision < 19) - return FLOAT; - - if (scale > 4 || precision > 19) - return DOUBLE; - - return NUMERIC; - } - else { - if (precision < 1) - return INTEGER; - - if (precision < 2) - return BOOLEAN; - - if (precision < 4) - return TINYINT; - - if (precision < 6) - return SMALLINT; - - if (precision < 11) - return INTEGER; - - if (precision < 20) - return BIGINT; - - return NUMERIC; - } - - case "DATE": - return DATE; - - case "BFILE": - case "BLOB": - return BLOB; - - case "CLOB": - case "NCLOB": - return CLOB; - - case "XMLTYPE": - return SQLXML; - } - } - - return OTHER; - } - - /** - * Retrieve primary key columns. - * - * @param stmt Prepared SQL statement to execute. - * @param owner DB owner. - * @param tbl Table name. - * @return Primary key columns. - * @throws SQLException If failed to retrieve primary key columns. - */ - private Set<String> primaryKeys(PreparedStatement stmt, String owner, String tbl) throws SQLException { - Set<String> pkCols = new HashSet<>(); - - stmt.setString(1, owner); - stmt.setString(2, tbl); - - try (ResultSet pkRs = stmt.executeQuery()) { - while(pkRs.next()) - pkCols.add(pkRs.getString(1)); - } - - return pkCols; - } - - /** - * Retrieve index columns. - * - * @param stmt Prepared SQL statement to execute. - * @param owner DB owner. - * @param tbl Table name. - * @return Indexes. - * @throws SQLException If failed to retrieve indexes columns. - */ - private Collection<QueryIndex> indexes(PreparedStatement stmt, String owner, String tbl) - throws SQLException { - Map<String, QueryIndex> idxs = new LinkedHashMap<>(); - - stmt.setString(1, owner); - stmt.setString(2, tbl); - - try (ResultSet idxsRs = stmt.executeQuery()) { - while (idxsRs.next()) { - String idxName = idxsRs.getString(IDX_NAME_IDX); - - QueryIndex idx = idxs.get(idxName); - - if (idx == null) { - idx = new QueryIndex(); - idx.setName(idxName); - idx.setIndexType(QueryIndexType.SORTED); - idx.setFields(new LinkedHashMap<String, Boolean>()); - - idxs.put(idxName, idx); - } - - String expr = idxsRs.getString(IDX_EXPR_IDX); - - String col = expr == null ? idxsRs.getString(IDX_COL_NAME_IDX) : expr.replaceAll("\"", ""); - - idx.getFields().put(col, !"DESC".equals(idxsRs.getString(IDX_COL_DESCEND_IDX))); - } - } - - return idxs.values(); - } - - /** {@inheritDoc} */ - @Override public Collection<DbTable> tables(Connection conn, List<String> schemas, boolean tblsOnly) - throws SQLException { - Collection<DbTable> tbls = new ArrayList<>(); - - PreparedStatement pkStmt = conn.prepareStatement(SQL_PRIMARY_KEYS); - - PreparedStatement idxStmt = conn.prepareStatement(SQL_INDEXES); - - if (schemas.isEmpty()) - schemas.add(null); - - Set<String> sysSchemas = systemSchemas(); - - try (Statement colsStmt = conn.createStatement()) { - for (String schema: schemas) { - if (systemSchemas().contains(schema) || (schema != null && schema.startsWith("FLOWS_"))) - continue; - - Collection<DbColumn> cols = new ArrayList<>(); - - Set<String> pkCols = Collections.emptySet(); - Collection<QueryIndex> idxs = Collections.emptyList(); - - String sql = String.format(SQL_COLUMNS, - tblsOnly ? "INNER JOIN all_tables b on a.table_name = b.table_name and a.owner = b.owner" : "", - schema != null ? String.format(" WHERE a.owner = '%s' ", schema) : ""); - - try (ResultSet colsRs = colsStmt.executeQuery(sql)) { - String prevSchema = ""; - String prevTbl = ""; - - boolean first = true; - - while (colsRs.next()) { - String owner = colsRs.getString(OWNER_IDX); - String tbl = colsRs.getString(TBL_NAME_IDX); - - if (sysSchemas.contains(owner) || (schema != null && schema.startsWith("FLOWS_"))) - continue; - - boolean changed = !owner.equals(prevSchema) || !tbl.equals(prevTbl); - - if (changed) { - if (first) - first = false; - else - tbls.add(table(prevSchema, prevTbl, cols, idxs)); - - prevSchema = owner; - prevTbl = tbl; - cols = new ArrayList<>(); - pkCols = primaryKeys(pkStmt, owner, tbl); - idxs = indexes(idxStmt, owner, tbl); - } - - String colName = colsRs.getString(COL_NAME_IDX); - - cols.add(new DbColumn(colName, decodeType(colsRs), pkCols.contains(colName), - !"N".equals(colsRs.getString(NULLABLE_IDX)))); - } - - if (!cols.isEmpty()) - tbls.add(table(prevSchema, prevTbl, cols, idxs)); - } - } - } - - return tbls; - } -}
