Skip to content

Commit 4dcfaf6

Browse files
authored
Merge pull request #6 from schemacrawler/command
Use command pattern for AI functions
2 parents 67b25e8 + 604bfa3 commit 4dcfaf6

17 files changed

+182
-100
lines changed

.github/workflows/quick_build.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,28 @@ jobs:
2525
uses: sualeh/prepare-maven-build@v1.4.0
2626
with:
2727
java-version: 21
28+
- id: install-graphviz
29+
name: Install Graphviz
30+
uses: sualeh/install-graphviz@v1.0.3
31+
32+
# BUILD DEPENDENCIES
33+
- id: checkout-schemacrawler
34+
name: Checkout SchemaCrawler
35+
uses: actions/checkout@v4
36+
with:
37+
repository: schemacrawler/SchemaCrawler
38+
path: SchemaCrawler
39+
- id: build-schemacrawler
40+
name: Build SchemaCrawler for local Maven repository
41+
shell: bash
42+
run: |
43+
# Build SchemaCrawler
44+
cd SchemaCrawler
45+
mvn \
46+
--no-transfer-progress \
47+
--batch-mode \
48+
-Dmaven.test.skip=true \
49+
clean install
2850
2951
# BUILD AND TEST
3052
- id: build-test

src/main/java/schemacrawler/tools/command/aichat/AiChatCommand.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ public void checkAvailability() throws RuntimeException {
5353

5454
@Override
5555
public void execute() {
56-
try (AiChatConsole aiChatConsole =
57-
new AiChatConsole(commandOptions, catalog, connection); ) {
56+
try (AiChatConsole aiChatConsole = new AiChatConsole(commandOptions, catalog, connection); ) {
5857
aiChatConsole.console();
5958
}
6059
}

src/main/java/schemacrawler/tools/command/aichat/AiChatCommandProvider.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ public PluginCommand getCommandLineCommand() {
5555
.addOption("api-key", String.class, "OpenAI API key")
5656
.addOption(
5757
"api-key:env", String.class, "OpenAI API key, from an environmental variable value")
58-
.addOption(
59-
"model", String.class, "AI chat model", "Optional, defaults to 'gpt-4o-mini'")
58+
.addOption("model", String.class, "AI chat model", "Optional, defaults to 'gpt-4o-mini'")
6059
.addOption(
6160
"timeout",
6261
Integer.class,
@@ -86,7 +85,7 @@ public AiChatCommand newSchemaCrawlerCommand(final String command, final Config
8685
AiChatCommandOptionsBuilder.builder().fromConfig(config).toOptions();
8786

8887
final AiChatCommand scCommand = new AiChatCommand();
89-
scCommand.setCommandOptions(options);
88+
scCommand.configure(options);
9089
return scCommand;
9190
} catch (final Exception e) {
9291
throw new ExecutionRuntimeException(e);

src/main/java/schemacrawler/tools/command/aichat/FunctionExecutor.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,12 @@
2828

2929
package schemacrawler.tools.command.aichat;
3030

31-
import java.sql.Connection;
3231
import java.util.UUID;
33-
import java.util.concurrent.Callable;
34-
import schemacrawler.schema.Catalog;
32+
import schemacrawler.tools.executable.Command;
3533

36-
public interface FunctionExecutor<P extends FunctionParameters> extends Callable<FunctionReturn> {
34+
public interface FunctionExecutor<P extends FunctionParameters> extends Command<P, FunctionReturn> {
3735

3836
String getDescription();
3937

4038
UUID getExecutorInstanceId();
41-
42-
String getName();
43-
44-
void initialize(P args, Catalog catalog, Connection connection);
4539
}

src/main/java/schemacrawler/tools/command/aichat/functions/AbstractFunctionExecutor.java

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ protected AbstractFunctionExecutor(final PropertyName functionName) {
5454
executorInstanceId = UUID.randomUUID();
5555
}
5656

57+
@Override
58+
public void configure(final P args) {
59+
this.args = requireNonNull(args, "No arguments provided");
60+
}
61+
5762
@Override
5863
public boolean equals(final Object obj) {
5964
if (this == obj) {
@@ -66,6 +71,16 @@ public boolean equals(final Object obj) {
6671
return Objects.equals(args, other.args);
6772
}
6873

74+
@Override
75+
public Catalog getCatalog() {
76+
return catalog;
77+
}
78+
79+
@Override
80+
public Connection getConnection() {
81+
return connection;
82+
}
83+
6984
@Override
7085
public final String getDescription() {
7186
return functionName.getDescription();
@@ -86,6 +101,24 @@ public int hashCode() {
86101
return Objects.hash(args);
87102
}
88103

104+
@Override
105+
public void initialize() {
106+
// No-op
107+
}
108+
109+
@Override
110+
public void setCatalog(final Catalog catalog) {
111+
this.catalog = requireNonNull(catalog, "Catalog is not provided");
112+
}
113+
114+
@Override
115+
public void setConnection(final Connection connection) {
116+
if (!usesConnection()) {
117+
throw new ExecutionRuntimeException("Function does not use a connection");
118+
}
119+
this.connection = requireNonNull(connection, "Connection is not provided");
120+
}
121+
89122
@Override
90123
public String toString() {
91124
return String.format(
@@ -94,15 +127,4 @@ public String toString() {
94127
new KebabCaseStrategy().translate(args.getClass().getSimpleName()),
95128
getDescription());
96129
}
97-
98-
@Override
99-
public void initialize(final P args, final Catalog catalog, final Connection connection) {
100-
this.args = requireNonNull(args, "No arguments provided");
101-
if (catalog == null) {
102-
throw new ExecutionRuntimeException("Catalog is not provided");
103-
}
104-
this.catalog = catalog;
105-
// Connection can be null
106-
this.connection = connection;
107-
}
108130
}

src/main/java/schemacrawler/tools/command/aichat/functions/LintFunctionExecutor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,9 @@ protected String getCommand() {
7575
protected Function<Catalog, Boolean> getResultsChecker() {
7676
return catalog -> !catalog.getTables().isEmpty();
7777
}
78+
79+
@Override
80+
public boolean usesConnection() {
81+
return true;
82+
}
7883
}

src/main/java/schemacrawler/tools/command/aichat/utility/AiChatUtility.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,12 @@ public static <P extends FunctionParameters> String execute(
7777
try {
7878
final schemacrawler.tools.command.aichat.FunctionExecutor<P> functionExecutor =
7979
functionDefinitionToCall.newExecutor();
80-
functionExecutor.initialize(parameters, catalog, connection);
80+
functionExecutor.configure(parameters);
81+
functionExecutor.initialize();
82+
functionExecutor.setCatalog(catalog);
83+
if (functionExecutor.usesConnection()) {
84+
functionExecutor.setConnection(connection);
85+
}
8186
functionReturn = functionExecutor.call();
8287
return functionReturn.get();
8388
} catch (final Exception e) {
@@ -108,7 +113,7 @@ public static boolean isExitCondition(final List<ChatMessage> completions) {
108113
public static FunctionExecutor newFunctionExecutor() {
109114

110115
final List<FunctionDef> chatFunctions = new ArrayList<>();
111-
for (final FunctionDefinition functionDefinition :
116+
for (final FunctionDefinition<?> functionDefinition :
112117
FunctionDefinitionRegistry.getFunctionDefinitionRegistry().getFunctionDefinitions()) {
113118
if (functionDefinition.getFunctionType() != FunctionType.USER) {
114119
continue;

src/test/java/schemacrawler/tools/command/aichat/function/test/DatabaseObjectDescriptionFunctionTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ private void describeDatabaseObject(
159159
try (final TestWriter out = testout) {
160160
final FunctionExecutor<DatabaseObjectDescriptionFunctionParameters> executor =
161161
functionDefinition.newExecutor();
162-
executor.initialize(args, catalog, null);
162+
executor.configure(args);
163+
executor.setCatalog(catalog);
163164
final FunctionReturn functionReturn = executor.call();
164165
out.write(functionReturn.get());
165166
}

src/test/java/schemacrawler/tools/command/aichat/function/test/DatabaseObjectListFunctionTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ private void databaseObjects(
142142
try (final TestWriter out = testout) {
143143
final FunctionExecutor<DatabaseObjectListFunctionParameters> executor =
144144
functionDefinition.newExecutor();
145-
executor.initialize(args, catalog, null);
145+
executor.configure(args);
146+
executor.setCatalog(catalog);
146147
final FunctionReturn functionReturn = executor.call();
147148
out.write(functionReturn.get());
148149
}

src/test/java/schemacrawler/tools/command/aichat/function/test/ExitFunctionTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ public void exit(final TestContext testContext) throws Exception {
5959
final TestWriter testout = new TestWriter();
6060
try (final TestWriter out = testout) {
6161
final FunctionExecutor<NoParameters> executor = functionDefinition.newExecutor();
62-
executor.initialize(args, mock(Catalog.class), null);
62+
executor.configure(args);
63+
executor.setCatalog(mock(Catalog.class));
6364
final FunctionReturn functionReturn = executor.call();
6465
out.write(functionReturn.get());
6566
}

0 commit comments

Comments
 (0)