/src/community/smart-data-loader/src/main/java/org/geoserver/smartdataloader/metadata/jdbc/JdbcHelper.java

https://github.com/geoserver/geoserver · Java · 563 lines · 513 code · 31 blank · 19 comment · 105 complexity · 0373fe492d1e0419f990ec510df37841 MD5 · raw file

  1. /* (c) 2021 Open Source Geospatial Foundation - all rights reserved
  2. * This code is licensed under the GPL 2.0 license, available at the root
  3. * application directory.
  4. */
  5. package org.geoserver.smartdataloader.metadata.jdbc;
  6. import com.google.common.collect.SortedSetMultimap;
  7. import com.google.common.collect.TreeMultimap;
  8. import java.sql.DatabaseMetaData;
  9. import java.sql.ResultSet;
  10. import java.util.ArrayList;
  11. import java.util.Collection;
  12. import java.util.Iterator;
  13. import java.util.List;
  14. import java.util.SortedMap;
  15. import java.util.TreeMap;
  16. import org.geoserver.smartdataloader.domain.entities.DomainRelationType;
  17. import org.geoserver.smartdataloader.metadata.AttributeMetadata;
  18. import org.geoserver.smartdataloader.metadata.EntityMetadata;
  19. import org.geoserver.smartdataloader.metadata.RelationMetadata;
  20. import org.geoserver.smartdataloader.metadata.jdbc.constraint.JdbcForeignKeyConstraintMetadata;
  21. import org.geoserver.smartdataloader.metadata.jdbc.constraint.JdbcIndexConstraintMetadata;
  22. import org.geoserver.smartdataloader.metadata.jdbc.constraint.JdbcPrimaryKeyConstraintMetadata;
  23. import org.geotools.jdbc.JDBCDataStore;
  24. /**
  25. * JDBC utilities singleton class. It encapsulates a GeoTools JDBCDataStore instance in order to use
  26. * some useful methods and extends it based on JDBC API use.
  27. */
  28. public class JdbcHelper {
  29. private static JdbcHelper single_instance = null;
  30. private JDBCDataStore jdbcDataStore;
  31. private JdbcHelper() {
  32. jdbcDataStore = new JDBCDataStore();
  33. }
  34. public static JdbcHelper getInstance() {
  35. if (single_instance == null) single_instance = new JdbcHelper();
  36. return single_instance;
  37. }
  38. private List<JdbcTableMetadata> getListOfTablesFromResultSet(
  39. DatabaseMetaData metaData, ResultSet tables) throws Exception {
  40. if (tables != null) {
  41. List<JdbcTableMetadata> tableList = new ArrayList<>();
  42. while (tables.next()) {
  43. if (tables.getString("TABLE_TYPE") != null
  44. && tables.getString("TABLE_TYPE").equals("TABLE")) {
  45. tableList.add(
  46. new JdbcTableMetadata(
  47. metaData.getConnection(),
  48. tables.getString("TABLE_CAT"),
  49. tables.getString("TABLE_SCHEM"),
  50. tables.getString("TABLE_NAME")));
  51. }
  52. }
  53. return tableList;
  54. }
  55. return null;
  56. }
  57. public List<JdbcTableMetadata> getSchemaTables(DatabaseMetaData metaData, String schema)
  58. throws Exception {
  59. try (ResultSet tables =
  60. metaData.getTables(
  61. null, jdbcDataStore.escapeNamePattern(metaData, schema), "%", null)) {
  62. return getListOfTablesFromResultSet(metaData, tables);
  63. }
  64. }
  65. public List<JdbcTableMetadata> getTables(DatabaseMetaData metaData) throws Exception {
  66. try (ResultSet tables = metaData.getTables(null, null, "%", null)) {
  67. return getListOfTablesFromResultSet(metaData, tables);
  68. }
  69. }
  70. public SortedMap<EntityMetadata, JdbcPrimaryKeyConstraintMetadata> getPrimaryKeyColumns(
  71. DatabaseMetaData metaData, List<JdbcTableMetadata> tables) throws Exception {
  72. if (tables != null) {
  73. SortedMap<EntityMetadata, JdbcPrimaryKeyConstraintMetadata> pkMap = new TreeMap<>();
  74. for (EntityMetadata table : tables) {
  75. JdbcPrimaryKeyConstraintMetadata primaryKey =
  76. getPrimaryKeyColumnsByTable(metaData, (JdbcTableMetadata) table);
  77. if (primaryKey != null) {
  78. pkMap.put(table, primaryKey);
  79. }
  80. }
  81. return pkMap;
  82. }
  83. return null;
  84. }
  85. public SortedMap<JdbcTableMetadata, List<AttributeMetadata>> getColumns(
  86. DatabaseMetaData metaData, List<JdbcTableMetadata> tables) throws Exception {
  87. if (tables != null) {
  88. SortedMap<JdbcTableMetadata, List<AttributeMetadata>> cMap = new TreeMap<>();
  89. for (JdbcTableMetadata table : tables) {
  90. List<AttributeMetadata> columnList = getColumnsByTable(metaData, table);
  91. if (columnList != null) {
  92. cMap.put(table, columnList);
  93. }
  94. }
  95. return cMap;
  96. }
  97. return null;
  98. }
  99. public JdbcPrimaryKeyConstraintMetadata getPrimaryKeyColumnsByTable(
  100. DatabaseMetaData metaData, JdbcTableMetadata table) throws Exception {
  101. ResultSet primaryKeyColumns =
  102. (table != null)
  103. ? metaData.getPrimaryKeys(
  104. table.getCatalog(), table.getSchema(), table.getName())
  105. : null;
  106. if (primaryKeyColumns != null && primaryKeyColumns.next()) {
  107. JdbcTableMetadata pkTable =
  108. new JdbcTableMetadata(
  109. metaData.getConnection(),
  110. primaryKeyColumns.getString("TABLE_CAT"),
  111. primaryKeyColumns.getString("TABLE_SCHEM"),
  112. primaryKeyColumns.getString("TABLE_NAME"));
  113. String pkConstraintName = primaryKeyColumns.getString("PK_NAME");
  114. List<String> pkColumnNames = new ArrayList<>();
  115. do {
  116. pkColumnNames.add(primaryKeyColumns.getString("COLUMN_NAME"));
  117. } while (primaryKeyColumns.next());
  118. JdbcPrimaryKeyConstraintMetadata primaryKey =
  119. new JdbcPrimaryKeyConstraintMetadata(pkTable, pkConstraintName, pkColumnNames);
  120. return primaryKey;
  121. }
  122. return null;
  123. }
  124. public List<AttributeMetadata> getColumnsByTable(
  125. DatabaseMetaData metaData, JdbcTableMetadata table) throws Exception {
  126. ResultSet columns =
  127. (table != null)
  128. ? metaData.getColumns(
  129. table.getCatalog(), table.getSchema(), table.getName(), "%")
  130. : null;
  131. if (columns != null && columns.next()) {
  132. JdbcTableMetadata aTable =
  133. new JdbcTableMetadata(
  134. metaData.getConnection(),
  135. columns.getString("TABLE_CAT"),
  136. columns.getString("TABLE_SCHEM"),
  137. columns.getString("TABLE_NAME"));
  138. List<AttributeMetadata> columnsList = new ArrayList<>();
  139. do {
  140. boolean isFK = isForeignKey(metaData, aTable, columns.getString("COLUMN_NAME"));
  141. boolean isPK = isPrimaryKey(metaData, aTable, columns.getString("COLUMN_NAME"));
  142. JdbcColumnMetadata aColumn =
  143. new JdbcColumnMetadata(
  144. aTable,
  145. columns.getString("COLUMN_NAME"),
  146. columns.getString("TYPE_NAME"),
  147. isFK,
  148. isPK);
  149. columnsList.add(aColumn);
  150. } while (columns.next());
  151. return columnsList;
  152. }
  153. return null;
  154. }
  155. public List<RelationMetadata> getRelationsByTable(
  156. DatabaseMetaData metaData, JdbcTableMetadata table) throws Exception {
  157. ArrayList<RelationMetadata> relations = new ArrayList<>();
  158. // add all foreignkeys relations
  159. SortedMap<JdbcForeignKeyConstraintMetadata, Collection<JdbcForeignKeyColumnMetadata>>
  160. fkMap = JdbcHelper.getInstance().getForeignKeysByTable(metaData, table);
  161. if (fkMap != null) {
  162. Iterator<JdbcForeignKeyConstraintMetadata> iFkConstraint = fkMap.keySet().iterator();
  163. while (iFkConstraint.hasNext()) {
  164. JdbcForeignKeyConstraintMetadata key = iFkConstraint.next();
  165. Collection<JdbcForeignKeyColumnMetadata> fkColumns = fkMap.get(key);
  166. Iterator<JdbcForeignKeyColumnMetadata> iFkColumns = fkColumns.iterator();
  167. while (iFkColumns.hasNext()) {
  168. JdbcForeignKeyColumnMetadata aFkColumn = iFkColumns.next();
  169. DomainRelationType type = JdbcHelper.getInstance().getCardinality(table, key);
  170. JdbcRelationMetadata relation =
  171. new JdbcRelationMetadata(key.getName(), type, aFkColumn);
  172. relations.add(relation);
  173. table.addRelation(relation);
  174. }
  175. }
  176. }
  177. // add all inverted foreignkeys relations
  178. SortedMap<JdbcForeignKeyConstraintMetadata, Collection<JdbcForeignKeyColumnMetadata>>
  179. iFkMap = JdbcHelper.getInstance().getInversedForeignKeysByTable(metaData, table);
  180. if (iFkMap != null) {
  181. Iterator<JdbcForeignKeyConstraintMetadata> iFkConstraint = iFkMap.keySet().iterator();
  182. while (iFkConstraint.hasNext()) {
  183. JdbcForeignKeyConstraintMetadata key = iFkConstraint.next();
  184. Collection<JdbcForeignKeyColumnMetadata> fkColumns = iFkMap.get(key);
  185. Iterator<JdbcForeignKeyColumnMetadata> iFkColumns = fkColumns.iterator();
  186. while (iFkColumns.hasNext()) {
  187. JdbcForeignKeyColumnMetadata aFkColumn = iFkColumns.next();
  188. DomainRelationType type = DomainRelationType.ONEMANY;
  189. JdbcRelationMetadata relation =
  190. new JdbcRelationMetadata(key.getName(), type, aFkColumn);
  191. relations.add(relation);
  192. table.addRelation(relation);
  193. }
  194. }
  195. }
  196. return relations;
  197. }
  198. public boolean isForeignKey(
  199. DatabaseMetaData metaData, JdbcTableMetadata table, String columnName)
  200. throws Exception {
  201. ResultSet foreignKeys =
  202. (table != null)
  203. ? metaData.getImportedKeys(
  204. table.getCatalog(), table.getSchema(), table.getName())
  205. : null;
  206. if (foreignKeys != null && foreignKeys.next()) {
  207. do {
  208. if (foreignKeys.getString("FKTABLE_SCHEM").equals(table.getSchema())
  209. && foreignKeys.getString("FKTABLE_NAME").equals(table.getName())
  210. && foreignKeys.getString("FKCOLUMN_NAME").equals(columnName)) {
  211. return true;
  212. }
  213. } while (foreignKeys.next());
  214. }
  215. return false;
  216. }
  217. public boolean isPrimaryKey(
  218. DatabaseMetaData metaData, JdbcTableMetadata table, String columnName)
  219. throws Exception {
  220. ResultSet primaryKey =
  221. (table != null)
  222. ? metaData.getPrimaryKeys(
  223. table.getCatalog(), table.getSchema(), table.getName())
  224. : null;
  225. if (primaryKey != null && primaryKey.next()) {
  226. do {
  227. if (primaryKey.getString("COLUMN_NAME").equals(columnName)) {
  228. return true;
  229. }
  230. } while (primaryKey.next());
  231. }
  232. return false;
  233. }
  234. public AttributeMetadata getColumnFromTable(
  235. DatabaseMetaData metaData, JdbcTableMetadata table, String columnName)
  236. throws Exception {
  237. ResultSet columns =
  238. (table != null)
  239. ? metaData.getColumns(
  240. table.getCatalog(), table.getSchema(), table.getName(), columnName)
  241. : null;
  242. if (columns != null && columns.next()) {
  243. JdbcTableMetadata aTable =
  244. new JdbcTableMetadata(
  245. metaData.getConnection(),
  246. columns.getString("TABLE_CAT"),
  247. columns.getString("TABLE_SCHEM"),
  248. columns.getString("TABLE_NAME"));
  249. boolean isFK = isForeignKey(metaData, aTable, columnName);
  250. boolean isPK = isPrimaryKey(metaData, aTable, columnName);
  251. JdbcColumnMetadata aColumn =
  252. new JdbcColumnMetadata(
  253. aTable,
  254. columns.getString("COLUMN_NAME"),
  255. columns.getString("TYPE_NAME"),
  256. isFK,
  257. isPK);
  258. return aColumn;
  259. }
  260. return null;
  261. }
  262. public SortedMap<String, Collection<String>> getIndexColumns(
  263. DatabaseMetaData metaData,
  264. List<JdbcTableMetadata> tables,
  265. boolean unique,
  266. boolean approximate)
  267. throws Exception {
  268. if (tables != null) {
  269. SortedMap<String, Collection<String>> indexMap = new TreeMap<>();
  270. for (JdbcTableMetadata table : tables) {
  271. SortedMap<String, Collection<String>> tableIndexMap =
  272. getIndexesByTable(metaData, table, unique, approximate);
  273. if (tableIndexMap != null) {
  274. indexMap.putAll(tableIndexMap);
  275. }
  276. }
  277. return indexMap;
  278. }
  279. return null;
  280. }
  281. public SortedMap<String, Collection<String>> getIndexesByTable(
  282. DatabaseMetaData metaData, JdbcTableMetadata table, boolean unique, boolean approximate)
  283. throws Exception {
  284. ResultSet indexColumns =
  285. (table != null)
  286. ? metaData.getIndexInfo(
  287. table.getCatalog(),
  288. table.getSchema(),
  289. table.getName(),
  290. unique,
  291. approximate)
  292. : null;
  293. if (indexColumns != null && indexColumns.next()) {
  294. SortedSetMultimap<String, String> indexMultimap = TreeMultimap.create();
  295. JdbcTableMetadata tableAux =
  296. new JdbcTableMetadata(
  297. metaData.getConnection(),
  298. indexColumns.getString("TABLE_CAT"),
  299. indexColumns.getString("TABLE_SCHEM"),
  300. indexColumns.getString("TABLE_NAME"));
  301. do {
  302. String indexConstraintName = indexColumns.getString("INDEX_NAME");
  303. JdbcIndexConstraintMetadata indexConstraint =
  304. new JdbcIndexConstraintMetadata(tableAux, indexConstraintName);
  305. String indexColumnName = indexColumns.getString("COLUMN_NAME");
  306. indexMultimap.put(indexConstraint.toString(), indexColumnName);
  307. } while (indexColumns.next());
  308. SortedMap<String, Collection<String>> indexMap = new TreeMap<>();
  309. indexMap.putAll(indexMultimap.asMap());
  310. return indexMap;
  311. }
  312. return null;
  313. }
  314. public SortedMap<JdbcForeignKeyConstraintMetadata, Collection<JdbcForeignKeyColumnMetadata>>
  315. getForeignKeys(DatabaseMetaData metaData, List<JdbcTableMetadata> tables)
  316. throws Exception {
  317. if (tables != null) {
  318. SortedMap<JdbcForeignKeyConstraintMetadata, Collection<JdbcForeignKeyColumnMetadata>>
  319. fkMap = new TreeMap<>();
  320. for (JdbcTableMetadata table : tables) {
  321. SortedMap<
  322. JdbcForeignKeyConstraintMetadata,
  323. Collection<JdbcForeignKeyColumnMetadata>>
  324. tableFKMap = getForeignKeysByTable(metaData, table);
  325. if (tableFKMap != null) {
  326. fkMap.putAll(tableFKMap);
  327. }
  328. }
  329. return fkMap;
  330. }
  331. return null;
  332. }
  333. public SortedMap<JdbcForeignKeyConstraintMetadata, Collection<JdbcForeignKeyColumnMetadata>>
  334. getForeignKeysByTable(DatabaseMetaData metaData, JdbcTableMetadata table)
  335. throws Exception {
  336. ResultSet foreignKeys =
  337. (table != null)
  338. ? metaData.getImportedKeys(
  339. table.getCatalog(), table.getSchema(), table.getName())
  340. : null;
  341. if (foreignKeys != null && foreignKeys.next()) {
  342. SortedSetMultimap<JdbcForeignKeyConstraintMetadata, JdbcForeignKeyColumnMetadata>
  343. fkMultimap = TreeMultimap.create();
  344. JdbcTableMetadata fkTable =
  345. new JdbcTableMetadata(
  346. metaData.getConnection(),
  347. foreignKeys.getString("FKTABLE_CAT"),
  348. foreignKeys.getString("FKTABLE_SCHEM"),
  349. foreignKeys.getString("FKTABLE_NAME"));
  350. // get FKColumn from table just in order to get datatype
  351. AttributeMetadata aColumn =
  352. this.getColumnFromTable(
  353. metaData, table, foreignKeys.getString("FKCOLUMN_NAME"));
  354. String columnType = aColumn.getType();
  355. do {
  356. String fkConstraintName = foreignKeys.getString("FK_NAME");
  357. JdbcTableMetadata pkTable =
  358. new JdbcTableMetadata(
  359. metaData.getConnection(),
  360. foreignKeys.getString("PKTABLE_CAT"),
  361. foreignKeys.getString("PKTABLE_SCHEM"),
  362. foreignKeys.getString("PKTABLE_NAME"));
  363. JdbcForeignKeyConstraintMetadata fkConstraint =
  364. new JdbcForeignKeyConstraintMetadata(fkTable, fkConstraintName, pkTable);
  365. JdbcForeignKeyColumnMetadata fkColumn =
  366. new JdbcForeignKeyColumnMetadata(
  367. fkTable,
  368. foreignKeys.getString("FKCOLUMN_NAME"),
  369. columnType,
  370. new JdbcColumnMetadata(
  371. pkTable,
  372. foreignKeys.getString("PKCOLUMN_NAME"),
  373. columnType,
  374. false));
  375. fkMultimap.put(fkConstraint, fkColumn);
  376. } while (foreignKeys.next());
  377. SortedMap<JdbcForeignKeyConstraintMetadata, Collection<JdbcForeignKeyColumnMetadata>>
  378. fkMap = new TreeMap<>();
  379. fkMap.putAll(fkMultimap.asMap());
  380. return fkMap;
  381. }
  382. return null;
  383. }
  384. public DomainRelationType getCardinality(
  385. JdbcTableMetadata table, JdbcForeignKeyConstraintMetadata fkConstraint)
  386. throws Exception {
  387. DatabaseMetaData metaData = table.getConnection().getMetaData();
  388. SortedMap<JdbcForeignKeyConstraintMetadata, Collection<JdbcForeignKeyColumnMetadata>>
  389. fkMultimap = JdbcHelper.getInstance().getForeignKeysByTable(metaData, table);
  390. JdbcPrimaryKeyConstraintMetadata primaryKey =
  391. JdbcHelper.getInstance().getPrimaryKeyColumnsByTable(metaData, table);
  392. SortedMap<EntityMetadata, JdbcPrimaryKeyConstraintMetadata> pkMap = new TreeMap<>();
  393. pkMap.put(table, primaryKey);
  394. SortedMap<String, Collection<String>> uniqueIndexMultimap =
  395. JdbcHelper.getInstance().getIndexesByTable(metaData, table, true, true);
  396. if (fkMultimap != null) {
  397. for (JdbcForeignKeyConstraintMetadata aFkConstraint : fkMultimap.keySet()) {
  398. if (aFkConstraint.equals(fkConstraint)) {
  399. Collection<JdbcForeignKeyColumnMetadata> fkColumnsList =
  400. fkMultimap.get(aFkConstraint);
  401. JdbcPrimaryKeyConstraintMetadata isPrimaryKey =
  402. JdbcHelper.getInstance()
  403. .isPrimaryKey(aFkConstraint.getTable(), fkColumnsList, pkMap);
  404. if (isPrimaryKey != null) {
  405. return DomainRelationType.ONEONE;
  406. } else {
  407. String uniqueIndexConstraint =
  408. JdbcHelper.getInstance()
  409. .isUniqueIndex(
  410. aFkConstraint.getTable(),
  411. fkColumnsList,
  412. uniqueIndexMultimap);
  413. if (uniqueIndexConstraint != null) {
  414. return DomainRelationType.ONEONE;
  415. } else {
  416. if (aFkConstraint.equals(fkConstraint))
  417. return DomainRelationType.MANYONE;
  418. else return DomainRelationType.ONEMANY;
  419. }
  420. }
  421. }
  422. }
  423. }
  424. return null;
  425. }
  426. public JdbcPrimaryKeyConstraintMetadata isPrimaryKey(
  427. JdbcTableMetadata table,
  428. Collection<JdbcForeignKeyColumnMetadata> fkColumnsList,
  429. SortedMap<EntityMetadata, JdbcPrimaryKeyConstraintMetadata> pkMap) {
  430. JdbcPrimaryKeyConstraintMetadata primaryKey = pkMap.get(table);
  431. if (primaryKey == null) {
  432. return null;
  433. }
  434. for (String columnName : primaryKey.getColumnNames()) {
  435. boolean containsPkColumnName = false;
  436. for (JdbcForeignKeyColumnMetadata fkColumns : fkColumnsList) {
  437. if (columnName.equals(fkColumns.getName())) {
  438. containsPkColumnName = true;
  439. }
  440. }
  441. if (!containsPkColumnName) {
  442. return null;
  443. }
  444. }
  445. return primaryKey;
  446. }
  447. public String isUniqueIndex(
  448. JdbcTableMetadata table,
  449. Collection<JdbcForeignKeyColumnMetadata> fkColumnsList,
  450. SortedMap<String, Collection<String>> uniqueIndexMap) {
  451. if (uniqueIndexMap == null) {
  452. return null;
  453. }
  454. indexLoop:
  455. for (String uniqueIndexConstraint : uniqueIndexMap.keySet()) {
  456. if (uniqueIndexConstraint.startsWith(table.toString() + " - ")) {
  457. Collection<String> uniqueIndexColumns = uniqueIndexMap.get(uniqueIndexConstraint);
  458. for (String uniqueIndexColumn : uniqueIndexColumns) {
  459. boolean containsUniqueIndexColumn = false;
  460. for (JdbcForeignKeyColumnMetadata fkColumns : fkColumnsList) {
  461. if (uniqueIndexColumn.equals(fkColumns.getName())) {
  462. containsUniqueIndexColumn = true;
  463. }
  464. }
  465. if (!containsUniqueIndexColumn) {
  466. continue indexLoop;
  467. }
  468. }
  469. return uniqueIndexConstraint;
  470. }
  471. }
  472. return null;
  473. }
  474. /**
  475. * @param metaData the Database metadata
  476. * @param table the table metadata to use to pick up the column metadata
  477. * @return a SortedMap mapping the foreignKeys metadata to the column metadata. Returns null if
  478. * no column referencing the table are found
  479. * @throws Exception
  480. */
  481. public SortedMap<JdbcForeignKeyConstraintMetadata, Collection<JdbcForeignKeyColumnMetadata>>
  482. getInversedForeignKeysByTable(DatabaseMetaData metaData, JdbcTableMetadata table)
  483. throws Exception {
  484. ResultSet foreignKeys =
  485. (table != null)
  486. ? metaData.getExportedKeys(
  487. table.getCatalog(), table.getSchema(), table.getName())
  488. : null;
  489. if (foreignKeys != null && foreignKeys.next()) {
  490. SortedSetMultimap<JdbcForeignKeyConstraintMetadata, JdbcForeignKeyColumnMetadata>
  491. inversedFkMultimap = TreeMultimap.create();
  492. do {
  493. JdbcTableMetadata pkTable =
  494. new JdbcTableMetadata(
  495. metaData.getConnection(),
  496. foreignKeys.getString("PKTABLE_CAT"),
  497. foreignKeys.getString("PKTABLE_SCHEM"),
  498. foreignKeys.getString("PKTABLE_NAME"));
  499. String pkConstraintName = foreignKeys.getString("PK_NAME");
  500. JdbcTableMetadata fkTable =
  501. new JdbcTableMetadata(
  502. metaData.getConnection(),
  503. foreignKeys.getString("FKTABLE_CAT"),
  504. foreignKeys.getString("FKTABLE_SCHEM"),
  505. foreignKeys.getString("FKTABLE_NAME"));
  506. JdbcForeignKeyConstraintMetadata pkConstraint =
  507. new JdbcForeignKeyConstraintMetadata(pkTable, pkConstraintName, fkTable);
  508. // get FKColumn from table just in order to get datatype
  509. AttributeMetadata aColumn =
  510. this.getColumnFromTable(
  511. metaData, fkTable, foreignKeys.getString("FKCOLUMN_NAME"));
  512. String columnType = aColumn.getType();
  513. JdbcForeignKeyColumnMetadata fkColumns =
  514. new JdbcForeignKeyColumnMetadata(
  515. fkTable,
  516. foreignKeys.getString("FKCOLUMN_NAME"),
  517. columnType,
  518. new JdbcColumnMetadata(
  519. pkTable,
  520. foreignKeys.getString("PKCOLUMN_NAME"),
  521. columnType,
  522. false));
  523. inversedFkMultimap.put(pkConstraint, fkColumns);
  524. } while (foreignKeys.next());
  525. SortedMap<JdbcForeignKeyConstraintMetadata, Collection<JdbcForeignKeyColumnMetadata>>
  526. inversedFkMap = new TreeMap<>();
  527. inversedFkMap.putAll(inversedFkMultimap.asMap());
  528. return inversedFkMap;
  529. }
  530. return null;
  531. }
  532. }