From fc0a3e9754e4a2ab83b092b3a9564ba5cedc96d5 Mon Sep 17 00:00:00 2001 From: carm Date: Wed, 17 Aug 2022 03:16:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(metadata):=20=E6=96=B0=E5=A2=9E=E6=95=B0?= =?UTF-8?q?=E4=B8=AA=E5=B8=B8=E7=94=A8Metadata=E8=AF=BB=E5=8F=96=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=96=B9=E6=B3=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cc/carm/lib/easysql/api/SQLManager.java | 35 +++++++++++++++-- .../api/builder/TableMetadataBuilder.java | 38 ++++++++++++++++++- .../easysql/api/function/SQLBiFunction.java | 24 ++++++++++++ .../impl/TableMetadataBuilderImpl.java | 38 +++++++++++++++++-- .../lib/easysql/manager/SQLManagerImpl.java | 16 ++++---- 5 files changed, 132 insertions(+), 19 deletions(-) create mode 100644 api/src/main/java/cc/carm/lib/easysql/api/function/SQLBiFunction.java diff --git a/api/src/main/java/cc/carm/lib/easysql/api/SQLManager.java b/api/src/main/java/cc/carm/lib/easysql/api/SQLManager.java index 01240c5..10661ee 100644 --- a/api/src/main/java/cc/carm/lib/easysql/api/SQLManager.java +++ b/api/src/main/java/cc/carm/lib/easysql/api/SQLManager.java @@ -5,6 +5,7 @@ import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction; import cc.carm.lib.easysql.api.action.SQLUpdateAction; import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction; import cc.carm.lib.easysql.api.builder.*; +import cc.carm.lib.easysql.api.function.SQLBiFunction; import cc.carm.lib.easysql.api.function.SQLDebugHandler; import cc.carm.lib.easysql.api.function.SQLExceptionHandler; import cc.carm.lib.easysql.api.function.SQLFunction; @@ -187,11 +188,13 @@ public interface SQLManager { /** * 获取并操作 {@link DatabaseMetaData} 以得到需要的数据库消息。 * - * @param metadata 操作与返回的方法 - * @param 最终结果的返回类型 + * @param reader 操作与读取的方法 + * @param 最终结果的返回类型 * @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。 */ - CompletableFuture fetchMetadata(@NotNull SQLFunction metadata); + default CompletableFuture fetchMetadata(@NotNull SQLFunction reader) { + return fetchMetadata((meta, conn) -> reader.apply(meta)); + } /** * 获取并操作 {@link DatabaseMetaData} 提供的指定 {@link ResultSet} 以得到需要的数据库消息。 @@ -203,7 +206,31 @@ public interface SQLManager { * @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。 * @throws NullPointerException 当 supplier 提供的 {@link ResultSet} 为NULL时抛出 */ - CompletableFuture fetchMetadata(@NotNull SQLFunction supplier, + default CompletableFuture fetchMetadata(@NotNull SQLFunction supplier, + @NotNull SQLFunction<@NotNull ResultSet, R> reader) { + return fetchMetadata((meta, conn) -> supplier.apply(meta), reader); + } + + /** + * 获取并操作 {@link DatabaseMetaData} 以得到需要的数据库消息。 + * + * @param reader 操作与读取的方法 + * @param 最终结果的返回类型 + * @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。 + */ + CompletableFuture fetchMetadata(@NotNull SQLBiFunction reader); + + /** + * 获取并操作 {@link DatabaseMetaData} 提供的指定 {@link ResultSet} 以得到需要的数据库消息。 + *
该方法会自动关闭 {@link ResultSet} 。 + * + * @param supplier 操作 {@link DatabaseMetaData} 以提供信息所在的 {@link ResultSet} + * @param reader 读取 {@link ResultSet} 中指定信息的方法 + * @param 最终结果的返回类型 + * @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。 + * @throws NullPointerException 当 supplier 提供的 {@link ResultSet} 为NULL时抛出 + */ + CompletableFuture fetchMetadata(@NotNull SQLBiFunction supplier, @NotNull SQLFunction<@NotNull ResultSet, R> reader); /** diff --git a/api/src/main/java/cc/carm/lib/easysql/api/builder/TableMetadataBuilder.java b/api/src/main/java/cc/carm/lib/easysql/api/builder/TableMetadataBuilder.java index 5b207d3..63c68e9 100644 --- a/api/src/main/java/cc/carm/lib/easysql/api/builder/TableMetadataBuilder.java +++ b/api/src/main/java/cc/carm/lib/easysql/api/builder/TableMetadataBuilder.java @@ -1,7 +1,13 @@ package cc.carm.lib.easysql.api.builder; import cc.carm.lib.easysql.api.SQLBuilder; +import cc.carm.lib.easysql.api.function.SQLFunction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; +import java.sql.ResultSet; +import java.util.Set; import java.util.concurrent.CompletableFuture; public interface TableMetadataBuilder extends SQLBuilder { @@ -12,10 +18,38 @@ public interface TableMetadataBuilder extends SQLBuilder { CompletableFuture validateExist(); /** - * @param columnName 需要判断的列名 + * 对表内的数据列元数据进行读取 + * + * @param columnPattern 列的名称匹配表达式, 为空则匹配所有列 + * @param reader 读取的方法 + * @param 结果类型 + * @return 读取结果 + */ + CompletableFuture fetchColumns(@Nullable String columnPattern, + @NotNull SQLFunction reader); + + /** + * @param columnPattern 需要判断的列名表达式 * @return 对应列是否存在 */ - CompletableFuture isColumnExists(String columnName); + CompletableFuture isColumnExists(@NotNull String columnPattern); + + /** + * 列出所有表内的全部列。 + * + * @return 表内全部数据列的列名 + */ + default CompletableFuture<@Unmodifiable Set> listColumns() { + return listColumns(null); + } + + /** + * 列出所有满足表达式的列。 + * + * @param columnPattern 列名表达式,为空则列出全部 + * @return 所有满足表达式的列名 + */ + CompletableFuture<@Unmodifiable Set> listColumns(@Nullable String columnPattern); // More coming soon. diff --git a/api/src/main/java/cc/carm/lib/easysql/api/function/SQLBiFunction.java b/api/src/main/java/cc/carm/lib/easysql/api/function/SQLBiFunction.java new file mode 100644 index 0000000..ca4883a --- /dev/null +++ b/api/src/main/java/cc/carm/lib/easysql/api/function/SQLBiFunction.java @@ -0,0 +1,24 @@ +package cc.carm.lib.easysql.api.function; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.sql.SQLException; +import java.util.Objects; + +@FunctionalInterface +public interface SQLBiFunction { + + @Nullable + R apply(@NotNull T t, @NotNull U u) throws SQLException; + + default SQLBiFunction then(@NotNull SQLFunction after) { + Objects.requireNonNull(after); + return (T t, U u) -> { + R r = apply(t, u); + if (r == null) return null; + else return after.apply(r); + }; + } + +} diff --git a/impl/src/main/java/cc/carm/lib/easysql/builder/impl/TableMetadataBuilderImpl.java b/impl/src/main/java/cc/carm/lib/easysql/builder/impl/TableMetadataBuilderImpl.java index c2d9b2d..8f2d33f 100644 --- a/impl/src/main/java/cc/carm/lib/easysql/builder/impl/TableMetadataBuilderImpl.java +++ b/impl/src/main/java/cc/carm/lib/easysql/builder/impl/TableMetadataBuilderImpl.java @@ -1,13 +1,20 @@ package cc.carm.lib.easysql.builder.impl; import cc.carm.lib.easysql.api.builder.TableMetadataBuilder; +import cc.carm.lib.easysql.api.function.SQLBiFunction; import cc.carm.lib.easysql.api.function.SQLFunction; import cc.carm.lib.easysql.builder.AbstractSQLBuilder; import cc.carm.lib.easysql.manager.SQLManagerImpl; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Optional; +import java.util.Set; import java.util.concurrent.CompletableFuture; public class TableMetadataBuilderImpl @@ -23,12 +30,35 @@ public class TableMetadataBuilderImpl @Override public CompletableFuture validateExist() { - return validate((meta) -> meta.getTables(null, null, tablePattern, new String[]{"TABLE"})); + return validate((meta, conn) -> meta.getTables(conn.getCatalog(), conn.getSchema(), tablePattern.toUpperCase(), new String[]{"TABLE"})); } @Override - public CompletableFuture isColumnExists(String columnPattern) { - return validate((meta) -> meta.getColumns(null, null, tablePattern, columnPattern)); + public CompletableFuture fetchColumns(@Nullable String columnPattern, + @NotNull SQLFunction reader) { + return getManager().fetchMetadata((meta, conn) -> meta.getColumns( + conn.getCatalog(), conn.getSchema(), tablePattern.toUpperCase(), + Optional.ofNullable(columnPattern).map(String::toUpperCase).orElse("%") + ), reader); + } + + @Override + public CompletableFuture isColumnExists(@NotNull String columnPattern) { + return validate((meta, conn) -> meta.getColumns( + conn.getCatalog(), conn.getSchema(), + tablePattern.toUpperCase(), columnPattern.toUpperCase() + )); + } + + @Override + public CompletableFuture> listColumns(@Nullable String columnPattern) { + return fetchColumns(columnPattern, (rs) -> { + Set data = new LinkedHashSet<>(); + while (rs.next()) { + data.add(rs.getString("COLUMN_NAME")); + } + return Collections.unmodifiableSet(data); + }); } /** @@ -37,7 +67,7 @@ public class TableMetadataBuilderImpl * @param supplier supplier to get result set * @return result future */ - private CompletableFuture validate(SQLFunction supplier) { + private CompletableFuture validate(SQLBiFunction supplier) { return getManager().fetchMetadata(supplier, ResultSet::next); } diff --git a/impl/src/main/java/cc/carm/lib/easysql/manager/SQLManagerImpl.java b/impl/src/main/java/cc/carm/lib/easysql/manager/SQLManagerImpl.java index 63cc07e..4178b42 100644 --- a/impl/src/main/java/cc/carm/lib/easysql/manager/SQLManagerImpl.java +++ b/impl/src/main/java/cc/carm/lib/easysql/manager/SQLManagerImpl.java @@ -10,6 +10,7 @@ import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction; import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction; import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction; import cc.carm.lib.easysql.api.builder.*; +import cc.carm.lib.easysql.api.function.SQLBiFunction; import cc.carm.lib.easysql.api.function.SQLDebugHandler; import cc.carm.lib.easysql.api.function.SQLExceptionHandler; import cc.carm.lib.easysql.api.function.SQLFunction; @@ -155,10 +156,10 @@ public class SQLManagerImpl implements SQLManager { } @Override - public CompletableFuture fetchMetadata(@NotNull SQLFunction metadata) { + public CompletableFuture fetchMetadata(@NotNull SQLBiFunction reader) { return CompletableFuture.supplyAsync(() -> { try (Connection conn = getConnection()) { - return metadata.apply(conn.getMetaData()); + return reader.apply(conn.getMetaData(), conn); } catch (SQLException ex) { throw new RuntimeException(ex); } @@ -166,19 +167,16 @@ public class SQLManagerImpl implements SQLManager { } @Override - public CompletableFuture fetchMetadata(@NotNull SQLFunction supplier, + public CompletableFuture fetchMetadata(@NotNull SQLBiFunction supplier, @NotNull SQLFunction<@NotNull ResultSet, R> reader) { - return CompletableFuture.supplyAsync(() -> { - try ( - Connection conn = getConnection(); - ResultSet rs = supplier.apply(conn.getMetaData()) - ) { + return fetchMetadata((meta, conn) -> { + try (ResultSet rs = supplier.apply(conn.getMetaData(), conn)) { if (rs == null) throw new NullPointerException("Metadata返回的ResultSet为null。"); else return reader.apply(rs); } catch (SQLException ex) { throw new RuntimeException(ex); } - }, this.executorPool); + }); } @Override