Search in sources :

Example 6 with DfForeignKeyMeta

use of org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta in project dbflute-core by dbflute.

the class DfForeignKeyExtractor method prepareUniqueKeyFkCache.

protected void prepareUniqueKeyFkCache(Connection conn, UnifiedSchema unifiedSchema) {
    // preparing unique-key FK info of the schema
    final Map<String, List<DfForeignKeyMeta>> tableMap = StringKeyMap.createAsFlexibleConcurrent();
    final DfUniqueKeyFkExtractor extractor = createUniqueKeyFkExtractor(conn, unifiedSchema);
    if (extractor == null) {
        // no need to extract in this DBMS
        _uniqueKeyFkMap.put(unifiedSchema, new ConcurrentHashMap<String, List<DfForeignKeyMeta>>());
        return;
    }
    _log.info("...Extracting unique-key FK: " + unifiedSchema);
    final Map<String, Map<String, List<UserUniqueFkColumn>>> uniqueKeyFkMap = extractor.extractUniqueKeyFkMap();
    for (Entry<String, Map<String, List<UserUniqueFkColumn>>> tableEntry : uniqueKeyFkMap.entrySet()) {
        final String tableKey = tableEntry.getKey();
        final List<DfForeignKeyMeta> metaList = new ArrayList<DfForeignKeyMeta>();
        final Map<String, List<UserUniqueFkColumn>> fkColumnListMap = tableEntry.getValue();
        for (Entry<String, List<UserUniqueFkColumn>> fkEntry : fkColumnListMap.entrySet()) {
            final List<UserUniqueFkColumn> columnList = fkEntry.getValue();
            DfForeignKeyMeta meta = null;
            for (UserUniqueFkColumn uniqueFkColumn : columnList) {
                if (meta == null) {
                    meta = new DfForeignKeyMeta();
                    meta.setForeignKeyName(uniqueFkColumn.getForeignKeyName());
                    meta.setLocalSchema(unifiedSchema);
                    meta.setLocalTablePureName(uniqueFkColumn.getLocalTableName());
                    // same schema only supported
                    meta.setForeignSchema(unifiedSchema);
                    final String foreignTableName = uniqueFkColumn.getForeignTableName();
                    meta.setForeignTablePureName(foreignTableName);
                    if (!isForeignTableGenerated(foreignTableName)) {
                        break;
                    }
                }
                meta.putColumnName(uniqueFkColumn.getLocalColumnName(), uniqueFkColumn.getForeignColumnName());
            }
            if (meta == null) {
                // basically no way
                throw new IllegalStateException("The key should have any elements: " + tableKey);
            }
            metaList.add(meta);
        }
        tableMap.put(tableKey, metaList);
    }
    _uniqueKeyFkMap.put(unifiedSchema, tableMap);
    if (!tableMap.isEmpty()) {
        _log.info(" -> Unique-key FK: " + tableMap.keySet());
    } else {
        _log.info(" -> Not found unique-key FK");
    }
}
Also used : DfUniqueKeyFkExtractor(org.dbflute.logic.jdbc.metadata.supplement.DfUniqueKeyFkExtractor) DfForeignKeyMeta(org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta) ArrayList(java.util.ArrayList) UserUniqueFkColumn(org.dbflute.logic.jdbc.metadata.supplement.DfUniqueKeyFkExtractor.UserUniqueFkColumn) ArrayList(java.util.ArrayList) List(java.util.List) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) TreeMap(java.util.TreeMap) StringKeyMap(org.dbflute.helper.StringKeyMap)

Example 7 with DfForeignKeyMeta

use of org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta in project dbflute-core by dbflute.

the class DfForeignKeyExtractor method filterSameStructureForeignKey.

protected Map<String, DfForeignKeyMeta> filterSameStructureForeignKey(Map<String, DfForeignKeyMeta> fkMap) {
    final Map<String, DfForeignKeyMeta> filteredFKMap = newLinkedHashMap();
    final Map<Map<String, Object>, Object> checkMap = newLinkedHashMap();
    final Object dummyObj = new Object();
    for (Entry<String, DfForeignKeyMeta> entry : fkMap.entrySet()) {
        final String foreinKeyName = entry.getKey();
        final DfForeignKeyMeta metaInfo = entry.getValue();
        final Map<String, Object> checkKey = newLinkedHashMap();
        checkKey.put(metaInfo.getForeignTableIdentityName(), dummyObj);
        checkKey.put("columnNameMap:" + metaInfo.getColumnNameMap(), dummyObj);
        if (checkMap.containsKey(checkKey)) {
            // basically no way
            String msg = "*The same-structural foreign key was found: skipped=" + foreinKeyName + ":" + checkKey;
            _log.warn(msg);
        } else {
            checkMap.put(checkKey, dummyObj);
            filteredFKMap.put(foreinKeyName, metaInfo);
        }
    }
    return filteredFKMap;
}
Also used : DfForeignKeyMeta(org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) TreeMap(java.util.TreeMap) StringKeyMap(org.dbflute.helper.StringKeyMap)

Example 8 with DfForeignKeyMeta

use of org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta in project dbflute-core by dbflute.

the class DfForeignKeyExtractor method doGetForeignKeyMap.

protected Map<String, DfForeignKeyMeta> doGetForeignKeyMap(Connection conn, DatabaseMetaData metaData, UnifiedSchema unifiedSchema, String tableName, boolean retry) throws SQLException {
    final Map<String, DfForeignKeyMeta> fkMap = newTableConstraintMap();
    if (isForeignKeyExtractingUnsupported()) {
        return fkMap;
    }
    final Map<String, String> exceptedFKMap = newLinkedHashMap();
    ResultSet rs = null;
    try {
        rs = extractForeignKeyMetaData(metaData, unifiedSchema, tableName, retry);
        if (rs == null) {
            return DfCollectionUtil.newHashMap();
        }
        while (rs.next()) {
            // /- - - - - - - - - - - - - - - - - - - - - - - -
            // same policy as table process about JDBC handling
            // (see DfTableHandler.java)
            // - - - - - - - - - -/
            final String localTableName = rs.getString(7);
            if (checkMetaTableDiffIfNeeds(tableName, localTableName)) {
                continue;
            }
            final String foreignCatalogName = rs.getString(1);
            final String foreignSchemaName = rs.getString(2);
            final String foreignTableName = rs.getString(3);
            final String foreignColumnName = rs.getString(4);
            final String localCatalogName = rs.getString(5);
            final String localSchemaName = rs.getString(6);
            final String localColumnName = rs.getString(8);
            final String fkName;
            {
                final String fkPlainName = rs.getString(12);
                if (Srl.is_NotNull_and_NotTrimmedEmpty(fkPlainName)) {
                    fkName = fkPlainName;
                } else {
                    // basically no way but SQLite comes here
                    // make it up automatically just in case
                    // (use local column name and foreign table name)
                    fkName = "FK_" + tableName + "_" + localColumnName + "_" + foreignTableName;
                    _log.info("...Making FK name (because of no name): " + fkName);
                }
            }
            // (basically if the foreign table is non-generate target, it is excepted)
            if (!isForeignTableGenerated(foreignTableName)) {
                exceptedFKMap.put(fkName, foreignTableName);
                continue;
            }
            // check except columns
            assertFKColumnNotExcepted(unifiedSchema, tableName, localColumnName);
            final UnifiedSchema foreignSchema = createAsDynamicSchema(foreignCatalogName, foreignSchemaName);
            assertPKColumnNotExcepted(foreignSchema, foreignTableName, foreignColumnName);
            DfForeignKeyMeta meta = fkMap.get(fkName);
            if (meta == null) {
                // basically here
                meta = new DfForeignKeyMeta();
                fkMap.put(fkName, meta);
            } else {
                // same-name FK was found!
                // pure name is enough for check
                final String firstName = meta.getForeignTablePureName();
                final String secondName = foreignTableName;
                if (firstName.equalsIgnoreCase(secondName)) {
                    // means compound FK
                    meta.putColumnName(localColumnName, foreignColumnName);
                    // putting columns only
                    continue;
                } else {
                    // here: same-name FK and same different foreign table.
                    // Basically no way!
                    // But DB2 returns to-ALIAS foreign key as same-name FK.
                    // Same type as local's type is prior
                    // and if types are different, use first.
                    final String msgBase = "...Handling same-name FK ";
                    if (judgeSameNameForeignKey(tableName, firstName, secondName)) {
                        // use first (skip current)
                        _log.info(msgBase + "(use first one): " + fkName + " to " + firstName);
                        continue;
                    } else {
                        // use second (override)
                        _log.info(msgBase + "(use second one): " + fkName + " to " + secondName);
                    }
                }
            }
            // first or override
            meta.setForeignKeyName(fkName);
            meta.setLocalSchema(createAsDynamicSchema(localCatalogName, localSchemaName));
            meta.setLocalTablePureName(localTableName);
            meta.setForeignSchema(foreignSchema);
            meta.setForeignTablePureName(foreignTableName);
            meta.putColumnName(localColumnName, foreignColumnName);
        }
    } finally {
        if (rs != null) {
            rs.close();
        }
    }
    reflectUniqueKeyFk(conn, unifiedSchema, tableName, fkMap);
    handleExceptedForeignKey(exceptedFKMap, tableName);
    return immobilizeOrder(filterSameStructureForeignKey(fkMap));
}
Also used : UnifiedSchema(org.apache.torque.engine.database.model.UnifiedSchema) DfForeignKeyMeta(org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta) ResultSet(java.sql.ResultSet)

Example 9 with DfForeignKeyMeta

use of org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta in project dbflute-core by dbflute.

the class DfSynonymExtractorOracle method setupDBLinkSynonym.

protected DfSynonymMeta setupDBLinkSynonym(Connection conn, DfSynonymMeta info, Map<String, Map<String, SynonymNativeInfo>> dbLinkSynonymNativeMap) throws SQLException {
    if (!info.isSelectable()) {
        // e.g. procedure synonym
        return info;
    }
    final String tableName = info.getTableName();
    final String dbLinkName = info.getDBLinkName();
    final String realTableName = translateTableName(tableName, dbLinkName, dbLinkSynonymNativeMap);
    final DfPrimaryKeyMeta pkInfo = getDBLinkSynonymPKInfo(conn, realTableName, dbLinkName);
    info.setPrimaryKey(pkInfo);
    final Map<String, Map<Integer, String>> uniqueKeyMap = getDBLinkSynonymUQMap(conn, realTableName, dbLinkName);
    info.setUniqueKeyMap(uniqueKeyMap);
    // Foreign Key and Index of DBLink are unsupported.
    info.setForeignKeyMap(new LinkedHashMap<String, DfForeignKeyMeta>());
    info.setIndexMap(new LinkedHashMap<String, Map<Integer, String>>());
    return info;
}
Also used : DfPrimaryKeyMeta(org.dbflute.logic.jdbc.metadata.info.DfPrimaryKeyMeta) DfForeignKeyMeta(org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) StringKeyMap(org.dbflute.helper.StringKeyMap)

Example 10 with DfForeignKeyMeta

use of org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta in project dbflute-core by dbflute.

the class DfSchemaXmlSerializer method getForeignKeys.

// -----------------------------------------------------
// Foreign Key
// -----------
/**
 * Retrieves a list of foreign key columns for a given table.
 * @param conn The connection for the foreign keys, basically for info cannot be provided from meta data, e.g. to-UQ FK. (NotNull)
 * @param metaData The meta data of a database. (NotNull)
 * @param tableMeta The meta information of table. (NotNull)
 * @return A list of foreign keys in <code>tableName</code>.
 * @throws SQLException When it fails to handle the SQL.
 */
protected Map<String, DfForeignKeyMeta> getForeignKeys(Connection conn, DatabaseMetaData metaData, DfTableMeta tableMeta) throws SQLException {
    final Map<String, DfForeignKeyMeta> foreignKeyMap = _foreignKeyExtractor.getForeignKeyMap(conn, metaData, tableMeta);
    if (!canHandleSynonym(tableMeta) || !foreignKeyMap.isEmpty()) {
        return foreignKeyMap;
    }
    final DfSynonymMeta synonym = getSynonymMetaInfo(tableMeta);
    return synonym != null ? synonym.getForeignKeyMap() : foreignKeyMap;
}
Also used : DfSynonymMeta(org.dbflute.logic.jdbc.metadata.info.DfSynonymMeta) DfForeignKeyMeta(org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta)

Aggregations

DfForeignKeyMeta (org.dbflute.logic.jdbc.metadata.info.DfForeignKeyMeta)11 Map (java.util.Map)3 StringKeyMap (org.dbflute.helper.StringKeyMap)3 ArrayList (java.util.ArrayList)2 List (java.util.List)2 TreeMap (java.util.TreeMap)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 UnifiedSchema (org.apache.torque.engine.database.model.UnifiedSchema)2 DfForeignKeyExtractor (org.dbflute.logic.jdbc.metadata.basic.DfForeignKeyExtractor)2 DfSynonymMeta (org.dbflute.logic.jdbc.metadata.info.DfSynonymMeta)2 DatabaseMetaData (java.sql.DatabaseMetaData)1 ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 Statement (java.sql.Statement)1 Comparator (java.util.Comparator)1 LinkedHashMap (java.util.LinkedHashMap)1 Entry (java.util.Map.Entry)1 SQLFailureException (org.dbflute.exception.SQLFailureException)1 DfPrimaryKeyMeta (org.dbflute.logic.jdbc.metadata.info.DfPrimaryKeyMeta)1 DfTableMeta (org.dbflute.logic.jdbc.metadata.info.DfTableMeta)1