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");
}
}
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;
}
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));
}
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;
}
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;
}
Aggregations