PageRenderTime 28ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/etlunit-core/src/main/java/org/bitbucket/bradleysmithllc/etlunit/util/jdbc/JdbcVisitors.java

https://bitbucket.org/bradleysmithllc/etl-unit
Java | 299 lines | 224 code | 53 blank | 22 comment | 5 complexity | dfe68eb24d266e5ba50b74bd7ad93bc5 MD5 | raw file
  1. package org.bitbucket.bradleysmithllc.etlunit.util.jdbc;
  2. /*
  3. * #%L
  4. * etlunit-core
  5. * %%
  6. * Copyright (C) 2010 - 2021 bradleysmithllc
  7. * %%
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. * #L%
  20. */
  21. import java.sql.*;
  22. import java.util.concurrent.atomic.AtomicInteger;
  23. import java.util.function.Consumer;
  24. public class JdbcVisitors {
  25. public static JdbcVisitorCommands withConnection(ExceptionalSupplier<Connection> withConnnection, ExceptionalConsumer<Connection> returnTo) throws Exception {
  26. Connection c = withConnnection.get();
  27. return new JdbcVisitorCommands(c, returnTo);
  28. }
  29. public static JdbcVisitorCommands withConnection(Connection withConnnection, ExceptionalConsumer<Connection> returnTo) throws Exception {
  30. return new JdbcVisitorCommands(withConnnection, returnTo);
  31. }
  32. public static JdbcVisitorCommands withPersistentConnection(ExceptionalSupplier<Connection> withConnnection) throws Exception {
  33. Connection c = withConnnection.get();
  34. return new JdbcVisitorCommands(c, (connection) -> {});
  35. }
  36. public static JdbcVisitorCommands withPersistentConnection(Connection withConnnection) throws Exception {
  37. return new JdbcVisitorCommands(withConnnection, (connection) -> {});
  38. }
  39. public static JdbcVisitorCommands withDisposableConnection(ExceptionalSupplier<Connection> withConnnection) throws Exception {
  40. Connection c = withConnnection.get();
  41. return new JdbcVisitorCommands(c, (connection) -> {connection.close();});
  42. }
  43. public static JdbcVisitorCommands withDisposableConnection(Connection withConnnection) throws Exception {
  44. return new JdbcVisitorCommands(withConnnection, (connection) -> {connection.close();});
  45. }
  46. public static class JdbcVisitorCommands {
  47. private final Connection connection;
  48. private final ExceptionalConsumer<Connection> returnTo;
  49. public JdbcVisitorCommands(Connection connection, ExceptionalConsumer<Connection> returnTo) {
  50. this.connection = connection;
  51. this.returnTo = returnTo;
  52. }
  53. public JdbcVisitorCommands withConnection(ExceptionalConsumer<Connection> consumer) throws Exception {
  54. consumer.accept(connection);
  55. return this;
  56. }
  57. public JdbcVisitorCommands withCatalogs(ExceptionalConsumer<String> consumer) throws Exception {
  58. return withDatabaseMetadata((meta) -> {
  59. scanResultSet(meta.getCatalogs(), (resultset) -> {
  60. String catalog = resultset.getString("TABLE_CAT");
  61. consumer.accept(catalog);
  62. });
  63. });
  64. }
  65. public JdbcVisitorCommands withSchemas(ExceptionalConsumer<MetadataSchema> consumer) throws Exception {
  66. return withSchemas(null, null, consumer);
  67. }
  68. public JdbcVisitorCommands withSchemas(String catalog, String schema, ExceptionalConsumer<MetadataSchema> consumer) throws Exception {
  69. return withDatabaseMetadata((meta) -> {
  70. scanResultSet(meta.getSchemas(catalog, schema), (resultset) -> {
  71. String catalogName = resultset.getString("TABLE_CATALOG");
  72. String schemaName = resultset.getString("TABLE_SCHEM");
  73. consumer.accept(new MetadataSchema(catalogName, schemaName));
  74. });
  75. });
  76. }
  77. public JdbcVisitorCommands withColumns(String catalog, String schema, String table, String column, ExceptionalConsumer<MetadataColumn> consumer) throws Exception {
  78. return withDatabaseMetadata((meta) -> {
  79. scanResultSet(meta.getColumns(catalog, schema, table, column), (resultset) -> {
  80. consumer.accept(
  81. new MetadataColumn(
  82. resultset.getString("TABLE_CAT"),
  83. resultset.getString("TABLE_SCHEM"),
  84. resultset.getString("TABLE_NAME"),
  85. resultset.getString("COLUMN_NAME")
  86. )
  87. .withDataType(resultset.getInt("DATA_TYPE"))
  88. .withColumnSize(resultset.getInt("COLUMN_SIZE"))
  89. .withDecimalDigits(resultset.getInt("DECIMAL_DIGITS"))
  90. .withNullable(resultset.getInt("NULLABLE"))
  91. .withSqlDataType(resultset.getInt("SQL_DATA_TYPE"))
  92. .withSqlDatetimeSub(resultset.getInt("SQL_DATETIME_SUB"))
  93. .withCharOctetLength(resultset.getInt("CHAR_OCTET_LENGTH"))
  94. .withOrdinalPosition(resultset.getInt("ORDINAL_POSITION"))
  95. .withSourceDataType(resultset.getShort("SOURCE_DATA_TYPE"))
  96. .withTypeName(resultset.getString("TYPE_NAME"))
  97. .withRemarks(resultset.getString("REMARKS"))
  98. .withColumnDef(resultset.getString("COLUMN_DEF"))
  99. .withIsNullable(resultset.getString("IS_NULLABLE"))
  100. .withScopeCatalog(resultset.getString("SCOPE_CATALOG"))
  101. .withScopeSchema(resultset.getString("SCOPE_SCHEMA"))
  102. .withScopeTable(resultset.getString("SCOPE_TABLE"))
  103. .withIsAutoincrement(resultset.getString("IS_AUTOINCREMENT"))
  104. .withIsGeneratedColumn(resultset.getString("IS_GENERATEDCOLUMN"))
  105. );
  106. });
  107. });
  108. }
  109. public JdbcVisitorCommands withTables(String catalog, String schema, String table, ExceptionalConsumer<MetadataTable> consumer) throws Exception {
  110. return withDatabaseMetadata((meta) -> {
  111. scanResultSet(meta.getTables(catalog, schema, table, null), (resultset) -> {
  112. consumer.accept(
  113. new MetadataTable(resultset.getString("TABLE_CAT"), resultset.getString("TABLE_SCHEM"), resultset.getString("TABLE_NAME"))
  114. .withRemarks(resultset.getString("REMARKS"))
  115. .withTableType(resultset.getString("TABLE_TYPE"))
  116. .withSelfReferencingColName(resultset.getString("SELF_REFERENCING_COL_NAME"))
  117. .withRefGeneration(resultset.getString("REF_GENERATION"))
  118. .withTypeCatalog(resultset.getString("TYPE_CAT"))
  119. .withTypeSchema(resultset.getString("TYPE_SCHEM"))
  120. .withTypeName(resultset.getString("TYPE_NAME"))
  121. );
  122. });
  123. });
  124. }
  125. public JdbcVisitorCommands withPrimaryKeys(String catalog, String schema, String table, ExceptionalConsumer<MetadataPrimaryKey> consumer) throws Exception {
  126. return withDatabaseMetadata((meta) -> {
  127. scanResultSet(meta.getPrimaryKeys(catalog, schema, table), (resultSet) -> {
  128. consumer.accept(new MetadataPrimaryKey(
  129. resultSet.getString("TABLE_CAT"),
  130. resultSet.getString("TABLE_SCHEM"),
  131. resultSet.getString("TABLE_NAME"),
  132. resultSet.getString("PK_NAME")
  133. )
  134. .withColumnName(resultSet.getString("COLUMN_NAME"))
  135. .withKeySequence(resultSet.getShort("KEY_SEQ"))
  136. );
  137. });
  138. });
  139. }
  140. public JdbcVisitorCommands withDatabaseMetadata(ExceptionalConsumer<DatabaseMetaData> st) throws Exception {
  141. st.accept(connection.getMetaData());
  142. return this;
  143. }
  144. public JdbcVisitorCommands withStatement(ExceptionalConsumer<Statement> st) throws Exception {
  145. Statement statement = connection.createStatement();
  146. try {
  147. st.accept(statement);
  148. } finally {
  149. statement.close();
  150. }
  151. return this;
  152. }
  153. public void withResultSet(ResultSet st, ExceptionalConsumer<ResultSet> consumer) throws Exception {
  154. try {
  155. consumer.accept(st);
  156. } finally {
  157. st.close();
  158. }
  159. }
  160. /* This version calls the consumer once for every single row. */
  161. public void scanResultSet(ResultSet st, ExceptionalConsumer<ResultSet> consumer) throws Exception {
  162. scanResultSet(st, consumer, (rowCount) -> {});
  163. }
  164. /* This version calls the consumer once for every single row. */
  165. public void scanResultSet(
  166. ResultSet st,
  167. ExceptionalConsumer<ResultSet> consumer,
  168. ExceptionalConsumer<Integer> allRowsComplete
  169. ) throws Exception {
  170. AtomicInteger rowCountRef = new AtomicInteger();
  171. try {
  172. withResultSet(st, (resultset) -> {
  173. while (resultset.next()) {
  174. rowCountRef.incrementAndGet();
  175. consumer.accept(resultset);
  176. }
  177. });
  178. } finally {
  179. st.close();
  180. }
  181. allRowsComplete.accept(rowCountRef.get());
  182. }
  183. public JdbcVisitorCommands scanQuery(String sql, ExceptionalConsumer<ResultSet> st) throws Exception {
  184. return scanQuery(sql, st, null, (rowCount) -> {});
  185. }
  186. public JdbcVisitorCommands withQuery(String sql, ExceptionalConsumer<ResultSet> st) throws Exception {
  187. return withQuery(sql, st, null);
  188. }
  189. /* Inject arbitrary code into the pipeline */
  190. public JdbcVisitorCommands withStep(Runnable step) throws Exception {
  191. step.run();
  192. return this;
  193. }
  194. public JdbcVisitorCommands withPreparedStatement(String sql, ExceptionalConsumer<PreparedStatement> st) throws Exception {
  195. PreparedStatement statement = connection.prepareStatement(sql);
  196. try {
  197. st.accept(statement);
  198. } finally {
  199. statement.close();
  200. }
  201. return this;
  202. }
  203. public JdbcVisitorCommands withUpdate(String sql, ExceptionalConsumer<Integer> st) throws Exception {
  204. withStatement((statement) -> {
  205. int resultSet = statement.executeUpdate(sql);
  206. st.accept(resultSet);
  207. });
  208. return this;
  209. }
  210. public JdbcVisitorCommands scanQuery(
  211. String sql,
  212. ExceptionalConsumer<ResultSet> st,
  213. ExceptionalConsumer<ResultSetMetaData> metadataConsumer
  214. ) throws Exception {
  215. return scanQuery(sql, st, metadataConsumer, (rowCount) -> {});
  216. }
  217. public JdbcVisitorCommands scanQuery(
  218. String sql,
  219. ExceptionalConsumer<ResultSet> st,
  220. ExceptionalConsumer<ResultSetMetaData> metadataConsumer,
  221. ExceptionalConsumer<Integer> completionConsumer
  222. ) throws Exception {
  223. withStatement((statement) -> {
  224. ResultSet resultSet = statement.executeQuery(sql);
  225. if (metadataConsumer != null) {
  226. metadataConsumer.accept(resultSet.getMetaData());
  227. }
  228. scanResultSet(resultSet, st, completionConsumer);
  229. });
  230. return this;
  231. }
  232. public JdbcVisitorCommands withQuery(String sql, ExceptionalConsumer<ResultSet> st, ExceptionalConsumer<ResultSetMetaData> metadataConsumer) throws Exception {
  233. withStatement((statement) -> {
  234. ResultSet resultSet = statement.executeQuery(sql);
  235. if (metadataConsumer != null) {
  236. metadataConsumer.accept(resultSet.getMetaData());
  237. }
  238. withResultSet(resultSet, st);
  239. });
  240. return this;
  241. }
  242. public void dispose() throws Exception {
  243. returnTo.accept(connection);
  244. }
  245. }
  246. }