Skip to content

Commit 35c1366

Browse files
authored
Merge pull request #146 from schemacrawler/allow-children
Allow Graphviz diagram output
2 parents d79038f + 9b39535 commit 35c1366

18 files changed

+200
-76
lines changed

.github/workflows/docker-image-early-release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ jobs:
110110
git push --delete origin early-access-release || true
111111
git tag -a early-access-release -m "SchemaCrawler AI Early Access Release"
112112
git push --follow-tags origin early-access-release
113-
git show early-access-release
113+
git show --no-patch early-access-release
114114
115115
# BUILD AND PUBLISH DOCKER IMAGE
116116
- id: setup-qemu

schemacrawler-ai-core/src/main/java/schemacrawler/tools/ai/functions/DescribeRoutinesFunctionParameters.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ public record DescribeRoutinesFunctionParameters(
2525
Name of database routine (stored procedure or function) to describe.
2626
May be specified as a regular expression matching the fully qualified
2727
stored procedure or function names (including the schema).
28-
Use an empty string if all routines are requested.
29-
If not specified, all routines are returned, but the results
30-
could be large.
28+
Try not to match all routines, but instead use a regular expression
29+
to match a subset, since otherwise results may be large.
3130
""")
3231
@JsonProperty(required = false)
3332
String routineName,

schemacrawler-ai-core/src/main/java/schemacrawler/tools/ai/functions/DescribeTablesFunctionExecutor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,11 @@ protected SchemaCrawlerOptions createSchemaCrawlerOptions() {
5454
.includeSequences(new ExcludeAll())
5555
.includeRoutines(new ExcludeAll())
5656
.includeTables(new IncludeAll());
57+
5758
final InclusionRule grepTablesPattern = makeInclusionRule(commandOptions.tableName());
5859
final GrepOptionsBuilder grepOptionsBuilder =
5960
GrepOptionsBuilder.builder().includeGreppedTables(grepTablesPattern);
61+
6062
return SchemaCrawlerOptionsBuilder.newSchemaCrawlerOptions()
6163
.withLimitOptions(limitOptionsBuilder.toOptions())
6264
.withGrepOptions(grepOptionsBuilder.toOptions());

schemacrawler-ai-core/src/main/java/schemacrawler/tools/ai/functions/DescribeTablesFunctionParameters.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ public record DescribeTablesFunctionParameters(
2525
Name of database table or view to describe.
2626
May be specified as a regular expression, matching the fully qualified
2727
table name (including the schema).
28-
Use an empty string if all tables are requested.
29-
If not specified, all tables will be returned, but the results
30-
could be large.
28+
Try not to match all tables, but instead use a regular expression
29+
to match a subset or match a single table, since otherwise results may
30+
be large.
3131
""")
3232
@JsonProperty(required = false)
3333
String tableName,

schemacrawler-ai-core/src/main/java/schemacrawler/tools/ai/functions/DiagramFunctionExecutor.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010

1111
import java.nio.file.Path;
1212
import schemacrawler.inclusionrule.InclusionRule;
13+
import schemacrawler.schemacrawler.FilterOptionsBuilder;
14+
import schemacrawler.schemacrawler.GrepOptionsBuilder;
15+
import schemacrawler.schemacrawler.SchemaCrawlerOptions;
16+
import schemacrawler.schemacrawler.SchemaCrawlerOptionsBuilder;
1317
import schemacrawler.tools.ai.functions.DiagramFunctionParameters.DiagramType;
1418
import schemacrawler.tools.ai.tools.FunctionReturn;
1519
import schemacrawler.tools.ai.tools.base.AbstractExecutableFunctionExecutor;
@@ -27,20 +31,45 @@ protected DiagramFunctionExecutor(final PropertyName functionName) {
2731

2832
@Override
2933
public FunctionReturn call() {
30-
final Config additionalConfig = createAdditionalConfig();
31-
final InclusionRule grepTablesInclusionRule = makeInclusionRule(commandOptions.tableName());
34+
final DiagramType diagramType = commandOptions.diagramType();
35+
final Config additionalConfig = createAdditionalConfig(diagramType);
3236
final ExecutionParameters executionParameters =
33-
new ExecutionParameters("script", additionalConfig, grepTablesInclusionRule, "text");
37+
new ExecutionParameters(
38+
diagramType.getCommand(), additionalConfig, diagramType.getOutputFormatValue());
3439
final Path outputFilePath = execute(executionParameters);
3540
return returnText(outputFilePath);
3641
}
3742

38-
private Config createAdditionalConfig() {
43+
@Override
44+
protected SchemaCrawlerOptions createSchemaCrawlerOptions() {
45+
final FilterOptionsBuilder filterOptionsBuilder = FilterOptionsBuilder.builder();
46+
if (commandOptions.includeChildTables()) {
47+
filterOptionsBuilder.childTableFilterDepth(1);
48+
}
49+
if (commandOptions.includeReferencedTables()) {
50+
filterOptionsBuilder.parentTableFilterDepth(1);
51+
}
52+
53+
final InclusionRule grepTablesInclusionRule = makeInclusionRule(commandOptions.tableName());
54+
final GrepOptionsBuilder grepOptionsBuilder =
55+
GrepOptionsBuilder.builder().includeGreppedTables(grepTablesInclusionRule);
56+
57+
final SchemaCrawlerOptions schemaCrawlerOptions =
58+
SchemaCrawlerOptionsBuilder.newSchemaCrawlerOptions()
59+
.withFilterOptions(filterOptionsBuilder.build())
60+
.withGrepOptions(grepOptionsBuilder.toOptions());
61+
return schemaCrawlerOptions;
62+
}
63+
64+
private Config createAdditionalConfig(final DiagramType diagramType) {
3965
final Config additionalConfig = ConfigUtility.newConfig();
66+
if (diagramType == null || diagramType == DiagramType.GRAPHVIZ) {
67+
return additionalConfig;
68+
}
4069

41-
final DiagramType diagramType = commandOptions.diagramType();
4270
additionalConfig.put("script-language", "python");
4371
additionalConfig.put("script", diagramType.script());
72+
4473
return additionalConfig;
4574
}
4675
}

schemacrawler-ai-core/src/main/java/schemacrawler/tools/ai/functions/DiagramFunctionParameters.java

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,39 +22,69 @@ public record DiagramFunctionParameters(
2222
Name of database table or view to describe.
2323
May be specified as a regular expression, matching the fully qualified
2424
table name (including the schema).
25-
Use an empty string if all tables are requested.
26-
If not specified, all tables will be returned, but the results
27-
could be large.
25+
Try not to match all tables, but instead use a regular expression
26+
to match a subset or match a single table, since otherwise results may
27+
be large.
2828
""")
2929
@JsonProperty(required = false)
3030
String tableName,
3131
@JsonPropertyDescription(
3232
"""
33-
Indicates database schema diagram format - Graphviz, PlantUML, Mermaid
34-
or DBML from dbdiagram.io.
33+
If true, also include child (or dependent) tables for the selected tables.
34+
""")
35+
@JsonProperty(required = false, defaultValue = "false")
36+
boolean includeChildTables,
37+
@JsonPropertyDescription(
38+
"""
39+
If true, also include tables that are referenced by the selected tables.
40+
(These are sometimes known as parent tables.)
41+
""")
42+
@JsonProperty(required = false, defaultValue = "false")
43+
boolean includeReferencedTables,
44+
@JsonPropertyDescription(
45+
"""
46+
Indicates database schema diagram format - Graphviz DOT format, PlantUML,
47+
Mermaid or DBML from dbdiagram.io.
3548
""")
3649
@JsonProperty(required = true)
3750
DiagramType diagramType)
3851
implements FunctionParameters {
3952

4053
public enum DiagramType {
41-
PLANTUML("/scripts/plantuml.py", "https://editor.plantuml.com/"),
42-
MERMAID("/scripts/mermaid.py", "https://mermaid.live/"),
43-
DBML("/scripts/dbml.py", "https://dbdiagram.io/d"),
54+
PLANTUML("script", "text", "/scripts/plantuml.py", "https://editor.plantuml.com/"),
55+
MERMAID("script", "text", "/scripts/mermaid.py", "https://mermaid.live/"),
56+
DBML("script", "text", "/scripts/dbml.py", "https://dbdiagram.io/d"),
57+
GRAPHVIZ("schema", "scdot", "", "https://dreampuf.github.io/GraphvizOnline/"),
4458
;
4559

60+
private final String command;
61+
private final String outputFormatValue;
4662
private final String script;
4763
private final String onlineEditorUrl;
4864

49-
DiagramType(final String script, final String url) {
65+
DiagramType(
66+
final String command,
67+
final String outputFormatValue,
68+
final String script,
69+
final String url) {
70+
this.command = command;
71+
this.outputFormatValue = outputFormatValue;
5072
this.script = script;
5173
onlineEditorUrl = url;
5274
}
5375

76+
public String getCommand() {
77+
return command;
78+
}
79+
5480
public String getOnlineEditorUrl() {
5581
return onlineEditorUrl;
5682
}
5783

84+
public String getOutputFormatValue() {
85+
return outputFormatValue;
86+
}
87+
5888
public String script() {
5989
return script;
6090
}

schemacrawler-ai-core/src/main/java/schemacrawler/tools/ai/functions/LintFunctionExecutor.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
import java.nio.file.Path;
1212
import schemacrawler.inclusionrule.InclusionRule;
13+
import schemacrawler.schemacrawler.GrepOptionsBuilder;
14+
import schemacrawler.schemacrawler.SchemaCrawlerOptions;
15+
import schemacrawler.schemacrawler.SchemaCrawlerOptionsBuilder;
1316
import schemacrawler.tools.ai.tools.FunctionReturn;
1417
import schemacrawler.tools.ai.tools.base.AbstractExecutableFunctionExecutor;
1518
import schemacrawler.tools.ai.tools.base.ExecutionParameters;
@@ -26,10 +29,19 @@ protected LintFunctionExecutor(final PropertyName functionName) {
2629
@Override
2730
public FunctionReturn call() {
2831
final String outputFormat = LintReportOutputFormat.json.name();
29-
final InclusionRule grepTablesInclusionRule = makeInclusionRule(commandOptions.tableName());
30-
final ExecutionParameters executionParameters =
31-
new ExecutionParameters("lint", grepTablesInclusionRule, outputFormat);
32+
final ExecutionParameters executionParameters = new ExecutionParameters("lint", outputFormat);
3233
final Path outputFilePath = execute(executionParameters);
3334
return returnJson(outputFilePath);
3435
}
36+
37+
@Override
38+
protected SchemaCrawlerOptions createSchemaCrawlerOptions() {
39+
final InclusionRule grepTablesInclusionRule = makeInclusionRule(commandOptions.tableName());
40+
final GrepOptionsBuilder grepOptionsBuilder =
41+
GrepOptionsBuilder.builder().includeGreppedTables(grepTablesInclusionRule);
42+
final SchemaCrawlerOptions schemaCrawlerOptions =
43+
SchemaCrawlerOptionsBuilder.newSchemaCrawlerOptions()
44+
.withGrepOptions(grepOptionsBuilder.toOptions());
45+
return schemaCrawlerOptions;
46+
}
3547
}

schemacrawler-ai-core/src/main/java/schemacrawler/tools/ai/functions/TableSampleFunctionExecutor.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
import java.nio.file.Path;
1212
import schemacrawler.inclusionrule.InclusionRule;
13+
import schemacrawler.schemacrawler.GrepOptionsBuilder;
14+
import schemacrawler.schemacrawler.SchemaCrawlerOptions;
15+
import schemacrawler.schemacrawler.SchemaCrawlerOptionsBuilder;
1316
import schemacrawler.tools.ai.tools.FunctionReturn;
1417
import schemacrawler.tools.ai.tools.base.AbstractExecutableFunctionExecutor;
1518
import schemacrawler.tools.ai.tools.base.ExecutionParameters;
@@ -24,10 +27,19 @@ protected TableSampleFunctionExecutor(final PropertyName functionName) {
2427

2528
@Override
2629
public FunctionReturn call() {
27-
final InclusionRule grepTablesInclusionRule = makeInclusionRule(commandOptions.tableName());
28-
final ExecutionParameters executionParameters =
29-
new ExecutionParameters("tablesample", grepTablesInclusionRule, "json");
30+
final ExecutionParameters executionParameters = new ExecutionParameters("tablesample", "json");
3031
final Path outputFilePath = execute(executionParameters);
3132
return returnJson(outputFilePath);
3233
}
34+
35+
@Override
36+
protected SchemaCrawlerOptions createSchemaCrawlerOptions() {
37+
final InclusionRule grepTablesInclusionRule = makeInclusionRule(commandOptions.tableName());
38+
final GrepOptionsBuilder grepOptionsBuilder =
39+
GrepOptionsBuilder.builder().includeGreppedTables(grepTablesInclusionRule);
40+
final SchemaCrawlerOptions schemaCrawlerOptions =
41+
SchemaCrawlerOptionsBuilder.newSchemaCrawlerOptions()
42+
.withGrepOptions(grepOptionsBuilder.toOptions());
43+
return schemaCrawlerOptions;
44+
}
3345
}

schemacrawler-ai-core/src/main/java/schemacrawler/tools/ai/tools/base/AbstractExecutableFunctionExecutor.java

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import java.util.logging.Level;
2222
import java.util.logging.Logger;
2323
import schemacrawler.inclusionrule.ExcludeAll;
24-
import schemacrawler.inclusionrule.InclusionRule;
25-
import schemacrawler.schemacrawler.GrepOptionsBuilder;
2624
import schemacrawler.schemacrawler.LimitOptionsBuilder;
2725
import schemacrawler.schemacrawler.SchemaCrawlerOptions;
2826
import schemacrawler.schemacrawler.SchemaCrawlerOptionsBuilder;
@@ -44,6 +42,7 @@
4442
import us.fatehi.utility.datasource.DatabaseConnectionSource;
4543
import us.fatehi.utility.datasource.DatabaseConnectionSources;
4644
import us.fatehi.utility.property.PropertyName;
45+
import us.fatehi.utility.string.StringFormat;
4746

4847
public abstract class AbstractExecutableFunctionExecutor<P extends FunctionParameters>
4948
extends AbstractFunctionExecutor<P> {
@@ -65,8 +64,7 @@ protected final Path execute(final ExecutionParameters executionParameters) {
6564
requireNonNull(executionParameters, "No execution parameters provided");
6665

6766
// Crate SchemaCrawler options
68-
final SchemaCrawlerOptions options =
69-
createSchemaCrawlerOptions(executionParameters.grepTablesInclusionRule());
67+
final SchemaCrawlerOptions options = adjustSchemaCrawlerOptions();
7068

7169
// Re-filter catalog
7270
MetaDataUtility.reduceCatalog(catalog, options);
@@ -84,8 +82,9 @@ protected final Path execute(final ExecutionParameters executionParameters) {
8482
final Config config = createAdditionalConfig(executionParameters.additionalConfig());
8583

8684
// Create executable
87-
final SchemaCrawlerExecutable executable =
88-
new SchemaCrawlerExecutable(executionParameters.command());
85+
final String command = executionParameters.command();
86+
LOGGER.log(Level.INFO, new StringFormat("Executing SchemaCrawler command <%s>", command));
87+
final SchemaCrawlerExecutable executable = new SchemaCrawlerExecutable(command);
8988
executable.setSchemaCrawlerOptions(options);
9089
executable.setCatalog(catalog);
9190
if (connection != null) {
@@ -143,6 +142,26 @@ protected final FunctionReturn returnText(final Path outputFilePath) {
143142
}
144143
}
145144

145+
private final SchemaCrawlerOptions adjustSchemaCrawlerOptions() {
146+
147+
final SchemaCrawlerOptions baseOptions = createSchemaCrawlerOptions();
148+
final LimitOptionsBuilder limitOptionsBuilder =
149+
LimitOptionsBuilder.builder()
150+
.includeSynonyms(new ExcludeAll())
151+
.includeSequences(new ExcludeAll())
152+
.includeRoutines(new ExcludeAll());
153+
SchemaCrawlerOptions schemaCrawlerOptions =
154+
SchemaCrawlerOptionsBuilder.newSchemaCrawlerOptions()
155+
.withLimitOptions(limitOptionsBuilder.toOptions());
156+
if (baseOptions != null) {
157+
schemaCrawlerOptions =
158+
schemaCrawlerOptions
159+
.withFilterOptions(baseOptions.filterOptions())
160+
.withGrepOptions(baseOptions.grepOptions());
161+
}
162+
return schemaCrawlerOptions;
163+
}
164+
146165
private Config createAdditionalConfig(final Config additionalConfig) {
147166
final Config config = SchemaTextOptionsBuilder.builder().noInfo().toConfig();
148167
config.merge(additionalConfig);
@@ -166,20 +185,6 @@ private OutputOptions createOutputOptions(final String outputFormatValue, final
166185
return outputOptions;
167186
}
168187

169-
private final SchemaCrawlerOptions createSchemaCrawlerOptions(
170-
final InclusionRule grepTablesInclusionRule) {
171-
final LimitOptionsBuilder limitOptionsBuilder =
172-
LimitOptionsBuilder.builder()
173-
.includeSynonyms(new ExcludeAll())
174-
.includeSequences(new ExcludeAll())
175-
.includeRoutines(new ExcludeAll());
176-
final GrepOptionsBuilder grepOptionsBuilder =
177-
GrepOptionsBuilder.builder().includeGreppedTables(grepTablesInclusionRule);
178-
return SchemaCrawlerOptionsBuilder.newSchemaCrawlerOptions()
179-
.withLimitOptions(limitOptionsBuilder.toOptions())
180-
.withGrepOptions(grepOptionsBuilder.toOptions());
181-
}
182-
183188
private void deleteTempFile(final Path outputFilePath) {
184189
if (outputFilePath == null) {
185190
return;

schemacrawler-ai-core/src/main/java/schemacrawler/tools/ai/tools/base/AbstractFunctionExecutor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import schemacrawler.inclusionrule.IncludeAll;
1616
import schemacrawler.inclusionrule.InclusionRule;
1717
import schemacrawler.inclusionrule.RegularExpressionInclusionRule;
18+
import schemacrawler.schemacrawler.SchemaCrawlerOptions;
1819
import schemacrawler.tools.ai.tools.FunctionExecutor;
1920
import schemacrawler.tools.ai.tools.FunctionParameters;
2021
import schemacrawler.tools.ai.tools.FunctionReturn;
@@ -33,6 +34,8 @@ public final String toString() {
3334
return command.getName();
3435
}
3536

37+
protected abstract SchemaCrawlerOptions createSchemaCrawlerOptions();
38+
3639
protected InclusionRule makeInclusionRule(final String objectName) {
3740
final InclusionRule inclusionRule;
3841
if (isBlank(objectName)) {

0 commit comments

Comments
 (0)