@memberjunction/db-auto-doc 6.2.0-edge.3 → 6.2.0-edge.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +200 -3
- package/dist/commands/analyze.d.ts +1 -0
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +6 -0
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/export.d.ts +32 -15
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +144 -14
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/core/AnalysisEngine.d.ts +15 -6
- package/dist/core/AnalysisEngine.d.ts.map +1 -1
- package/dist/core/AnalysisEngine.js +41 -40
- package/dist/core/AnalysisEngine.js.map +1 -1
- package/dist/core/AnalysisOrchestrator.d.ts +25 -1
- package/dist/core/AnalysisOrchestrator.d.ts.map +1 -1
- package/dist/core/AnalysisOrchestrator.js +163 -27
- package/dist/core/AnalysisOrchestrator.js.map +1 -1
- package/dist/core/PKProposalGate.d.ts +22 -0
- package/dist/core/PKProposalGate.d.ts.map +1 -0
- package/dist/core/PKProposalGate.js +52 -0
- package/dist/core/PKProposalGate.js.map +1 -0
- package/dist/database/Database.d.ts +8 -0
- package/dist/database/Database.d.ts.map +1 -1
- package/dist/database/Database.js +23 -1
- package/dist/database/Database.js.map +1 -1
- package/dist/discovery/EnumCandidateGate.d.ts +19 -0
- package/dist/discovery/EnumCandidateGate.d.ts.map +1 -1
- package/dist/discovery/EnumCandidateGate.js +47 -5
- package/dist/discovery/EnumCandidateGate.js.map +1 -1
- package/dist/discovery/FKGraphWalker.d.ts +35 -0
- package/dist/discovery/FKGraphWalker.d.ts.map +1 -1
- package/dist/discovery/FKGraphWalker.js +113 -12
- package/dist/discovery/FKGraphWalker.js.map +1 -1
- package/dist/discovery/LLMDiscoveryValidator.d.ts +2 -0
- package/dist/discovery/LLMDiscoveryValidator.d.ts.map +1 -1
- package/dist/discovery/LLMDiscoveryValidator.js +20 -9
- package/dist/discovery/LLMDiscoveryValidator.js.map +1 -1
- package/dist/discovery/OrganicKeyDetector.d.ts.map +1 -1
- package/dist/discovery/OrganicKeyDetector.js +8 -2
- package/dist/discovery/OrganicKeyDetector.js.map +1 -1
- package/dist/discovery/StructuralPhase.d.ts +27 -5
- package/dist/discovery/StructuralPhase.d.ts.map +1 -1
- package/dist/discovery/StructuralPhase.js +42 -9
- package/dist/discovery/StructuralPhase.js.map +1 -1
- package/dist/discovery/TransitiveBridgeDetector.d.ts +5 -1
- package/dist/discovery/TransitiveBridgeDetector.d.ts.map +1 -1
- package/dist/discovery/TransitiveBridgeDetector.js +25 -3
- package/dist/discovery/TransitiveBridgeDetector.js.map +1 -1
- package/dist/drivers/BaseAutoDocDriver.d.ts +6 -1
- package/dist/drivers/BaseAutoDocDriver.d.ts.map +1 -1
- package/dist/drivers/BaseAutoDocDriver.js +3 -5
- package/dist/drivers/BaseAutoDocDriver.js.map +1 -1
- package/dist/drivers/IndexCatalog.d.ts +54 -0
- package/dist/drivers/IndexCatalog.d.ts.map +1 -0
- package/dist/drivers/IndexCatalog.js +145 -0
- package/dist/drivers/IndexCatalog.js.map +1 -0
- package/dist/drivers/MySQLDriver.d.ts +5 -1
- package/dist/drivers/MySQLDriver.d.ts.map +1 -1
- package/dist/drivers/MySQLDriver.js +15 -6
- package/dist/drivers/MySQLDriver.js.map +1 -1
- package/dist/drivers/PostgreSQLDriver.d.ts +14 -2
- package/dist/drivers/PostgreSQLDriver.d.ts.map +1 -1
- package/dist/drivers/PostgreSQLDriver.js +52 -19
- package/dist/drivers/PostgreSQLDriver.js.map +1 -1
- package/dist/drivers/SQLServerDriver.d.ts +5 -1
- package/dist/drivers/SQLServerDriver.d.ts.map +1 -1
- package/dist/drivers/SQLServerDriver.js +13 -1
- package/dist/drivers/SQLServerDriver.js.map +1 -1
- package/dist/generators/AdditionalSchemaInfoGenerator.d.ts +34 -0
- package/dist/generators/AdditionalSchemaInfoGenerator.d.ts.map +1 -1
- package/dist/generators/AdditionalSchemaInfoGenerator.js +85 -4
- package/dist/generators/AdditionalSchemaInfoGenerator.js.map +1 -1
- package/dist/generators/ErdClusterGenerator.d.ts +44 -0
- package/dist/generators/ErdClusterGenerator.d.ts.map +1 -0
- package/dist/generators/ErdClusterGenerator.js +216 -0
- package/dist/generators/ErdClusterGenerator.js.map +1 -0
- package/dist/generators/ErdClusterer.d.ts +130 -0
- package/dist/generators/ErdClusterer.d.ts.map +1 -0
- package/dist/generators/ErdClusterer.js +308 -0
- package/dist/generators/ErdClusterer.js.map +1 -0
- package/dist/generators/HTMLGenerator.d.ts +6 -0
- package/dist/generators/HTMLGenerator.d.ts.map +1 -1
- package/dist/generators/HTMLGenerator.js +41 -6
- package/dist/generators/HTMLGenerator.js.map +1 -1
- package/dist/generators/MermaidGenerator.d.ts +3 -0
- package/dist/generators/MermaidGenerator.d.ts.map +1 -1
- package/dist/generators/MermaidGenerator.js +4 -0
- package/dist/generators/MermaidGenerator.js.map +1 -1
- package/dist/generators/index.d.ts +2 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +2 -0
- package/dist/generators/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/BaseAutoDocPlugin.d.ts +33 -0
- package/dist/plugins/BaseAutoDocPlugin.d.ts.map +1 -0
- package/dist/plugins/BaseAutoDocPlugin.js +70 -0
- package/dist/plugins/BaseAutoDocPlugin.js.map +1 -0
- package/dist/plugins/PluginManager.d.ts +54 -0
- package/dist/plugins/PluginManager.d.ts.map +1 -0
- package/dist/plugins/PluginManager.js +115 -0
- package/dist/plugins/PluginManager.js.map +1 -0
- package/dist/plugins/builtins.d.ts +13 -0
- package/dist/plugins/builtins.d.ts.map +1 -0
- package/dist/plugins/builtins.js +12 -0
- package/dist/plugins/builtins.js.map +1 -0
- package/dist/plugins/index-advisor/IndexAdvisorPlugin.d.ts +25 -0
- package/dist/plugins/index-advisor/IndexAdvisorPlugin.d.ts.map +1 -0
- package/dist/plugins/index-advisor/IndexAdvisorPlugin.js +128 -0
- package/dist/plugins/index-advisor/IndexAdvisorPlugin.js.map +1 -0
- package/dist/plugins/index-advisor/IndexAdvisorTypes.d.ts +111 -0
- package/dist/plugins/index-advisor/IndexAdvisorTypes.d.ts.map +1 -0
- package/dist/plugins/index-advisor/IndexAdvisorTypes.js +5 -0
- package/dist/plugins/index-advisor/IndexAdvisorTypes.js.map +1 -0
- package/dist/plugins/index-advisor/IndexLLMReview.d.ts +48 -0
- package/dist/plugins/index-advisor/IndexLLMReview.d.ts.map +1 -0
- package/dist/plugins/index-advisor/IndexLLMReview.js +181 -0
- package/dist/plugins/index-advisor/IndexLLMReview.js.map +1 -0
- package/dist/plugins/index-advisor/IndexMigrationGenerator.d.ts +28 -0
- package/dist/plugins/index-advisor/IndexMigrationGenerator.d.ts.map +1 -0
- package/dist/plugins/index-advisor/IndexMigrationGenerator.js +98 -0
- package/dist/plugins/index-advisor/IndexMigrationGenerator.js.map +1 -0
- package/dist/plugins/index-advisor/IndexRules.d.ts +19 -0
- package/dist/plugins/index-advisor/IndexRules.d.ts.map +1 -0
- package/dist/plugins/index-advisor/IndexRules.js +154 -0
- package/dist/plugins/index-advisor/IndexRules.js.map +1 -0
- package/dist/plugins/index.d.ts +13 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +13 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/types.d.ts +82 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +9 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/types/analysis.d.ts +2 -0
- package/dist/types/analysis.d.ts.map +1 -1
- package/dist/types/config.d.ts +52 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +7 -4
- package/dist/types/config.js.map +1 -1
- package/dist/types/discovery.d.ts +2 -0
- package/dist/types/discovery.d.ts.map +1 -1
- package/dist/types/driver.d.ts +30 -0
- package/dist/types/driver.d.ts.map +1 -1
- package/dist/types/driver.js +5 -1
- package/dist/types/driver.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/state.d.ts +36 -0
- package/dist/types/state.d.ts.map +1 -1
- package/dist/utils/config-loader.d.ts +5 -0
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +38 -1
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/index-hints.d.ts +36 -0
- package/dist/utils/index-hints.d.ts.map +1 -0
- package/dist/utils/index-hints.js +65 -0
- package/dist/utils/index-hints.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/llm-factory.d.ts +1 -0
- package/dist/utils/llm-factory.d.ts.map +1 -1
- package/dist/utils/llm-factory.js +6 -1
- package/dist/utils/llm-factory.js.map +1 -1
- package/package.json +5 -5
- package/prompts/fk-pruning-table.md +13 -1
- package/prompts/index-review.md +60 -0
- package/prompts/pk-pruning-table.md +10 -0
- package/prompts/table-analysis.md +11 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Database.js","sourceRoot":"","sources":["../../src/database/Database.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"Database.js","sourceRoot":"","sources":["../../src/database/Database.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,6 +48,13 @@ export declare class EnumCandidateGate {
|
|
|
48
48
|
* Returns an EnumCandidateContext if the column passes, or null if it doesn't.
|
|
49
49
|
*/
|
|
50
50
|
EvaluateColumn(column: ColumnDefinition, tableRowCount: number): EnumCandidateContext | null;
|
|
51
|
+
/**
|
|
52
|
+
* Checks an LLM value-list verdict against the data. The verdict counts only for a column that
|
|
53
|
+
* passes every gate here, and its values are cut down to the ones observed in that column, so a
|
|
54
|
+
* value the model invented never reaches the output. Returns the values to keep, or null when
|
|
55
|
+
* the verdict should be dropped (not a candidate, or fewer than two observed values remain).
|
|
56
|
+
*/
|
|
57
|
+
FilterVerdictValues(column: ColumnDefinition, tableRowCount: number, verdictValues: string[]): string[] | null;
|
|
51
58
|
/** @deprecated Use {@link EvaluateColumn}. */
|
|
52
59
|
evaluateColumn(column: ColumnDefinition, tableRowCount: number): EnumCandidateContext | null;
|
|
53
60
|
/**
|
|
@@ -57,6 +64,11 @@ export declare class EnumCandidateGate {
|
|
|
57
64
|
/**
|
|
58
65
|
* Gate: declared column length must be ≤ maxColumnLength.
|
|
59
66
|
* Unbounded text/varchar(max) is excluded.
|
|
67
|
+
*
|
|
68
|
+
* The drivers report the bare type name (`varchar`, `nvarchar`) with the length in
|
|
69
|
+
* `column.maxLength`, so the length comes from there when the type string carries none.
|
|
70
|
+
* Reading only the type string made every varchar/nvarchar column look unbounded, so no
|
|
71
|
+
* string column was ever a candidate.
|
|
60
72
|
*/
|
|
61
73
|
private passesColumnLengthGate;
|
|
62
74
|
/**
|
|
@@ -71,6 +83,11 @@ export declare class EnumCandidateGate {
|
|
|
71
83
|
* Gate: exclude key-shaped data patterns (sequential, guid, composite).
|
|
72
84
|
*/
|
|
73
85
|
private passesPatternGate;
|
|
86
|
+
/**
|
|
87
|
+
* Gate: the observed values must not all be years, GUIDs or dates. A year column grows every
|
|
88
|
+
* year, and GUIDs and dates are keys or timestamps, so none of them is a closed set.
|
|
89
|
+
*/
|
|
90
|
+
private passesValueShapeGate;
|
|
74
91
|
/**
|
|
75
92
|
* Gate: distinct count must be ≥ 2 and ≤ maxDistinctValues.
|
|
76
93
|
*/
|
|
@@ -86,6 +103,8 @@ export declare class EnumCandidateGate {
|
|
|
86
103
|
* e.g. "nvarchar(50)" → "nvarchar", "CHARACTER VARYING" → "character varying"
|
|
87
104
|
*/
|
|
88
105
|
private parseBaseType;
|
|
106
|
+
/** The declared length: from the type string when it carries one, else from the driver's maxLength. */
|
|
107
|
+
private declaredLength;
|
|
89
108
|
/**
|
|
90
109
|
* Parse the declared length from a type string.
|
|
91
110
|
* Returns null for unbounded types or types without length.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnumCandidateGate.d.ts","sourceRoot":"","sources":["../../src/discovery/EnumCandidateGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAoB,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,eAAe,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wDAAwD;IACxD,yBAAyB,EAAE,MAAM,EAAE,CAAC;CACrC;AAED,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"EnumCandidateGate.d.ts","sourceRoot":"","sources":["../../src/discovery/EnumCandidateGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAoB,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,eAAe,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wDAAwD;IACxD,yBAAyB,EAAE,MAAM,EAAE,CAAC;CACrC;AAED,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmCD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;gBAE5B,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAI5C;;OAEG;IACI,aAAa,CAClB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,aAAa,EAAE,MAAM,GACpB,oBAAoB,EAAE;IAWzB,6CAA6C;IACtC,aAAa,CAClB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,aAAa,EAAE,MAAM,GACpB,oBAAoB,EAAE;IAIzB;;;OAGG;IACI,cAAc,CACnB,MAAM,EAAE,gBAAgB,EACxB,aAAa,EAAE,MAAM,GACpB,oBAAoB,GAAG,IAAI;IA4B9B;;;;;OAKG;IACI,mBAAmB,CACxB,MAAM,EAAE,gBAAgB,EACxB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EAAE,GACtB,MAAM,EAAE,GAAG,IAAI;IAQlB,8CAA8C;IACvC,cAAc,CACnB,MAAM,EAAE,gBAAgB,EACxB,aAAa,EAAE,MAAM,GACpB,oBAAoB,GAAG,IAAI;IAM9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAM1B;;;;;;;;OAQG;IACH,OAAO,CAAC,sBAAsB;IAc9B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAI/B;;OAEG;IACH,OAAO,CAAC,aAAa;IAIrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAKzB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAI/B;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAa7B;;;OAGG;IACH,OAAO,CAAC,aAAa;IAMrB,uGAAuG;IACvG,OAAO,CAAC,cAAc;IAItB;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;;OAGG;IACH,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAgBxB;;;OAGG;IACH,OAAO,CAAC,eAAe;CAexB"}
|
|
@@ -19,8 +19,18 @@ const DEFAULT_CONFIG = {
|
|
|
19
19
|
/Description$/i,
|
|
20
20
|
/Comment$/i,
|
|
21
21
|
/Address/i,
|
|
22
|
+
// MJ's own system columns: their domain is defined by MJ, not by whatever a sample holds.
|
|
23
|
+
/^__mj_/i,
|
|
24
|
+
// Audit columns naming who wrote the row (e.g. CreatedBy, cst_add_user): a list of users, not a closed set.
|
|
25
|
+
/(^|_)(add|change|changed|create|created|modify|modified|update|updated|delete|deleted|insert|inserted)_?(user|usr|by|login)$/i,
|
|
22
26
|
],
|
|
23
27
|
};
|
|
28
|
+
/** Value shapes that make a column a poor closed list even when its cardinality is low. */
|
|
29
|
+
const VALUE_SHAPES_NOT_ENUM = [
|
|
30
|
+
/^(19|20)\d{2}$/, // years
|
|
31
|
+
/^\{?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}?$/i, // GUIDs
|
|
32
|
+
/^\d{4}-\d{2}-\d{2}([ T].*)?$/, // ISO dates and timestamps
|
|
33
|
+
];
|
|
24
34
|
/** Set of data-type base names eligible for enum detection (string types) */
|
|
25
35
|
const STRING_TYPES = new Set([
|
|
26
36
|
'char', 'nchar', 'varchar', 'nvarchar',
|
|
@@ -56,7 +66,7 @@ export class EnumCandidateGate {
|
|
|
56
66
|
EvaluateColumn(column, tableRowCount) {
|
|
57
67
|
if (!this.passesDataTypeGate(column.dataType))
|
|
58
68
|
return null;
|
|
59
|
-
if (!this.passesColumnLengthGate(column
|
|
69
|
+
if (!this.passesColumnLengthGate(column))
|
|
60
70
|
return null;
|
|
61
71
|
if (!this.passesNameExclusionGate(column.name))
|
|
62
72
|
return null;
|
|
@@ -74,6 +84,8 @@ export class EnumCandidateGate {
|
|
|
74
84
|
const values = this.extractValues(stats);
|
|
75
85
|
if (values.length < 2)
|
|
76
86
|
return null;
|
|
87
|
+
if (!this.passesValueShapeGate(values))
|
|
88
|
+
return null;
|
|
77
89
|
return {
|
|
78
90
|
columnName: column.name,
|
|
79
91
|
values,
|
|
@@ -81,9 +93,23 @@ export class EnumCandidateGate {
|
|
|
81
93
|
totalRows: tableRowCount,
|
|
82
94
|
cardinalityRatio: tableRowCount > 0 ? stats.distinctCount / tableRowCount : 1,
|
|
83
95
|
dataType: column.dataType,
|
|
84
|
-
maxLength: this.
|
|
96
|
+
maxLength: this.declaredLength(column) ?? undefined,
|
|
85
97
|
};
|
|
86
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Checks an LLM value-list verdict against the data. The verdict counts only for a column that
|
|
101
|
+
* passes every gate here, and its values are cut down to the ones observed in that column, so a
|
|
102
|
+
* value the model invented never reaches the output. Returns the values to keep, or null when
|
|
103
|
+
* the verdict should be dropped (not a candidate, or fewer than two observed values remain).
|
|
104
|
+
*/
|
|
105
|
+
FilterVerdictValues(column, tableRowCount, verdictValues) {
|
|
106
|
+
const candidate = this.EvaluateColumn(column, tableRowCount);
|
|
107
|
+
if (!candidate)
|
|
108
|
+
return null;
|
|
109
|
+
const observed = new Set(candidate.values);
|
|
110
|
+
const kept = verdictValues.filter(v => observed.has(v));
|
|
111
|
+
return kept.length >= 2 ? kept : null;
|
|
112
|
+
}
|
|
87
113
|
/** @deprecated Use {@link EvaluateColumn}. */
|
|
88
114
|
evaluateColumn(column, tableRowCount) {
|
|
89
115
|
return this.EvaluateColumn(column, tableRowCount);
|
|
@@ -100,10 +126,15 @@ export class EnumCandidateGate {
|
|
|
100
126
|
/**
|
|
101
127
|
* Gate: declared column length must be ≤ maxColumnLength.
|
|
102
128
|
* Unbounded text/varchar(max) is excluded.
|
|
129
|
+
*
|
|
130
|
+
* The drivers report the bare type name (`varchar`, `nvarchar`) with the length in
|
|
131
|
+
* `column.maxLength`, so the length comes from there when the type string carries none.
|
|
132
|
+
* Reading only the type string made every varchar/nvarchar column look unbounded, so no
|
|
133
|
+
* string column was ever a candidate.
|
|
103
134
|
*/
|
|
104
|
-
passesColumnLengthGate(
|
|
105
|
-
const baseType = this.parseBaseType(dataType);
|
|
106
|
-
const length = this.
|
|
135
|
+
passesColumnLengthGate(column) {
|
|
136
|
+
const baseType = this.parseBaseType(column.dataType);
|
|
137
|
+
const length = this.declaredLength(column);
|
|
107
138
|
// Unbounded text type — exclude
|
|
108
139
|
if (baseType === 'text' && length === null)
|
|
109
140
|
return false;
|
|
@@ -135,6 +166,13 @@ export class EnumCandidateGate {
|
|
|
135
166
|
return true;
|
|
136
167
|
return !EXCLUDED_PATTERNS.has(stats.dataPattern);
|
|
137
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Gate: the observed values must not all be years, GUIDs or dates. A year column grows every
|
|
171
|
+
* year, and GUIDs and dates are keys or timestamps, so none of them is a closed set.
|
|
172
|
+
*/
|
|
173
|
+
passesValueShapeGate(values) {
|
|
174
|
+
return !VALUE_SHAPES_NOT_ENUM.some(shape => values.every(v => shape.test(v)));
|
|
175
|
+
}
|
|
138
176
|
/**
|
|
139
177
|
* Gate: distinct count must be ≥ 2 and ≤ maxDistinctValues.
|
|
140
178
|
*/
|
|
@@ -163,6 +201,10 @@ export class EnumCandidateGate {
|
|
|
163
201
|
const base = dataType.replace(/\(.*\)/, '').trim().toLowerCase();
|
|
164
202
|
return base;
|
|
165
203
|
}
|
|
204
|
+
/** The declared length: from the type string when it carries one, else from the driver's maxLength. */
|
|
205
|
+
declaredLength(column) {
|
|
206
|
+
return this.parseDeclaredLength(column.dataType) ?? column.maxLength ?? null;
|
|
207
|
+
}
|
|
166
208
|
/**
|
|
167
209
|
* Parse the declared length from a type string.
|
|
168
210
|
* Returns null for unbounded types or types without length.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnumCandidateGate.js","sourceRoot":"","sources":["../../src/discovery/EnumCandidateGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA8BH,MAAM,cAAc,GAAmB;IACrC,eAAe,EAAE,EAAE;IACnB,iBAAiB,EAAE,EAAE;IACrB,YAAY,EAAE,EAAE;IAChB,mBAAmB,EAAE,IAAI;IACzB,yBAAyB,EAAE;QACzB,UAAU;QACV,eAAe;QACf,WAAW;QACX,UAAU;
|
|
1
|
+
{"version":3,"file":"EnumCandidateGate.js","sourceRoot":"","sources":["../../src/discovery/EnumCandidateGate.ts"],"names":[],"mappings":"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"}
|
|
@@ -85,6 +85,28 @@ export interface FKGraphWalkerOptions {
|
|
|
85
85
|
* Default true.
|
|
86
86
|
*/
|
|
87
87
|
PruneCycles?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Hard ceiling on the number of BFS states held at once for a single
|
|
90
|
+
* (spoke → hub) search. See {@link bfsPaths} for why an unbounded frontier
|
|
91
|
+
* is not a theoretical concern.
|
|
92
|
+
*/
|
|
93
|
+
MaxFrontier?: number;
|
|
94
|
+
/** Hard ceiling on the paths retained per (spoke → hub) search. */
|
|
95
|
+
MaxPathsPerPair?: number;
|
|
96
|
+
/** Hard ceiling on the paths retained across the whole walk. */
|
|
97
|
+
MaxTotalPaths?: number;
|
|
98
|
+
}
|
|
99
|
+
/** What a bounded walk found, and whether a bound stopped it finding more. */
|
|
100
|
+
export interface BridgePathWalkResult {
|
|
101
|
+
Paths: BridgePath[];
|
|
102
|
+
/** True when any cap (frontier, per-pair, or total) truncated the search. */
|
|
103
|
+
Truncated: boolean;
|
|
104
|
+
/** Which caps fired, for logging. Empty when the walk ran to completion. */
|
|
105
|
+
TruncationReasons: Array<'frontier' | 'pathsPerPair' | 'totalPaths'>;
|
|
106
|
+
/** (spoke, hub) pairs actually searched, after skipping pairs with no graph edge. */
|
|
107
|
+
PairsSearched: number;
|
|
108
|
+
/** (spoke, hub) pairs skipped because the spoke has no FK edge at all. */
|
|
109
|
+
PairsSkipped: number;
|
|
88
110
|
}
|
|
89
111
|
/**
|
|
90
112
|
* Build the join graph and find all bridge paths from each spoke candidate to
|
|
@@ -105,6 +127,19 @@ export declare function FindBridgePaths(edges: FKEdge[], hubs: Array<{
|
|
|
105
127
|
schema: string;
|
|
106
128
|
table: string;
|
|
107
129
|
}>, opts?: FKGraphWalkerOptions): BridgePath[];
|
|
130
|
+
/**
|
|
131
|
+
* The bounded walk. {@link FindBridgePaths} is the historical shape (paths only);
|
|
132
|
+
* this one also reports whether a bound truncated the search, which is the
|
|
133
|
+
* difference between "this schema has no bridges" and "we stopped looking".
|
|
134
|
+
*/
|
|
135
|
+
export declare function WalkBridgePaths(edges: FKEdge[], hubs: Array<{
|
|
136
|
+
schema: string;
|
|
137
|
+
table: string;
|
|
138
|
+
keyField: string;
|
|
139
|
+
}>, spokes: Array<{
|
|
140
|
+
schema: string;
|
|
141
|
+
table: string;
|
|
142
|
+
}>, opts?: FKGraphWalkerOptions): BridgePathWalkResult;
|
|
108
143
|
/** @deprecated Use {@link FindBridgePaths}. */
|
|
109
144
|
export declare function findBridgePaths(edges: FKEdge[], hubs: Array<{
|
|
110
145
|
schema: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FKGraphWalker.d.ts","sourceRoot":"","sources":["../../src/discovery/FKGraphWalker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,uDAAuD;AACvD,MAAM,WAAW,MAAM;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,sDAAsD;AACtD,MAAM,WAAW,UAAU;IACvB,gFAAgF;IAChF,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,qCAAqC;AACrC,MAAM,WAAW,SAAS;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACjC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"FKGraphWalker.d.ts","sourceRoot":"","sources":["../../src/discovery/FKGraphWalker.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,13 @@ const DEFAULTS = {
|
|
|
27
27
|
MaxHops: 3,
|
|
28
28
|
MinSoftFKConfidence: 0.6,
|
|
29
29
|
PruneCycles: true,
|
|
30
|
+
// THE NUMBERS ARE CEILINGS, NOT TUNING. They exist so that a graph nobody
|
|
31
|
+
// anticipated cannot take the process down; a schema that hits one is a
|
|
32
|
+
// schema whose bridge set was never going to be usable anyway, and the
|
|
33
|
+
// truncation is reported rather than swallowed.
|
|
34
|
+
MaxFrontier: 50_000,
|
|
35
|
+
MaxPathsPerPair: 50,
|
|
36
|
+
MaxTotalPaths: 25_000,
|
|
30
37
|
};
|
|
31
38
|
/**
|
|
32
39
|
* Build the join graph and find all bridge paths from each spoke candidate to
|
|
@@ -40,23 +47,69 @@ const DEFAULTS = {
|
|
|
40
47
|
* table in the database except the hub itself.
|
|
41
48
|
*/
|
|
42
49
|
export function FindBridgePaths(edges, hubs, spokes, opts = {}) {
|
|
43
|
-
|
|
50
|
+
return WalkBridgePaths(edges, hubs, spokes, opts).Paths;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The bounded walk. {@link FindBridgePaths} is the historical shape (paths only);
|
|
54
|
+
* this one also reports whether a bound truncated the search, which is the
|
|
55
|
+
* difference between "this schema has no bridges" and "we stopped looking".
|
|
56
|
+
*/
|
|
57
|
+
export function WalkBridgePaths(edges, hubs, spokes, opts = {}) {
|
|
58
|
+
// `{ ...DEFAULTS, ...opts }` would let an explicitly-undefined option UNSET a ceiling, which
|
|
59
|
+
// is the one way a caller could accidentally un-bound the walk. Only defined keys override.
|
|
60
|
+
const o = { ...DEFAULTS };
|
|
61
|
+
for (const key of Object.keys(DEFAULTS)) {
|
|
62
|
+
const supplied = opts[key];
|
|
63
|
+
if (supplied !== undefined) {
|
|
64
|
+
o[key] = supplied;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
44
67
|
// Build the adjacency map keyed by "schema.table".
|
|
45
68
|
const adjacency = buildAdjacency(edges, o.MinSoftFKConfidence);
|
|
69
|
+
const reasons = new Set();
|
|
46
70
|
const out = [];
|
|
47
|
-
|
|
71
|
+
let pairsSearched = 0;
|
|
72
|
+
let pairsSkipped = 0;
|
|
73
|
+
// GATE ON THE GRAPH, NOT ON THE INPUTS. An empty adjacency means no table is
|
|
74
|
+
// joined to any other, so every BFS below would dequeue its start node, find
|
|
75
|
+
// no neighbours and return nothing — `hubs × spokes` times.
|
|
76
|
+
if (adjacency.size === 0) {
|
|
77
|
+
return { Paths: [], Truncated: false, TruncationReasons: [], PairsSearched: 0, PairsSkipped: hubs.length * spokes.length };
|
|
78
|
+
}
|
|
79
|
+
outer: for (const hub of hubs) {
|
|
48
80
|
const hubKey = `${hub.schema}.${hub.table}`;
|
|
81
|
+
// A hub with no edge of its own is unreachable from every spoke.
|
|
82
|
+
if (!adjacency.has(hubKey)) {
|
|
83
|
+
pairsSkipped += spokes.length;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
49
86
|
for (const spoke of spokes) {
|
|
50
87
|
const spokeKey = `${spoke.schema}.${spoke.table}`;
|
|
51
88
|
if (spokeKey === hubKey)
|
|
52
89
|
continue;
|
|
90
|
+
// A spoke with no edge of its own cannot reach anything. Skipping it here is
|
|
91
|
+
// what turns "one BFS per hub × EVERY TABLE IN THE DATABASE" back into one
|
|
92
|
+
// BFS per hub × every table that is actually joined to something.
|
|
93
|
+
if (!adjacency.has(spokeKey)) {
|
|
94
|
+
pairsSkipped++;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
pairsSearched++;
|
|
53
98
|
// BFS from spoke → hub.
|
|
54
|
-
const
|
|
55
|
-
|
|
99
|
+
const search = bfsPaths(adjacency, spokeKey, hubKey, o.MaxHops, o.PruneCycles, o.MaxFrontier, o.MaxPathsPerPair);
|
|
100
|
+
if (search.frontierTruncated)
|
|
101
|
+
reasons.add('frontier');
|
|
102
|
+
if (search.pathsTruncated)
|
|
103
|
+
reasons.add('pathsPerPair');
|
|
104
|
+
for (const p of search.paths) {
|
|
56
105
|
if (p.length === 0)
|
|
57
106
|
continue; // self
|
|
58
107
|
if (p.length === 1)
|
|
59
108
|
continue; // direct FK already handled by existing relationship system
|
|
109
|
+
if (out.length >= o.MaxTotalPaths) {
|
|
110
|
+
reasons.add('totalPaths');
|
|
111
|
+
break outer;
|
|
112
|
+
}
|
|
60
113
|
out.push(materializeBridgePath(p, hub, spoke));
|
|
61
114
|
}
|
|
62
115
|
}
|
|
@@ -67,7 +120,13 @@ export function FindBridgePaths(edges, hubs, spokes, opts = {}) {
|
|
|
67
120
|
return a.PathLength - b.PathLength;
|
|
68
121
|
return b.PathConfidence - a.PathConfidence;
|
|
69
122
|
});
|
|
70
|
-
return
|
|
123
|
+
return {
|
|
124
|
+
Paths: out,
|
|
125
|
+
Truncated: reasons.size > 0,
|
|
126
|
+
TruncationReasons: [...reasons],
|
|
127
|
+
PairsSearched: pairsSearched,
|
|
128
|
+
PairsSkipped: pairsSkipped,
|
|
129
|
+
};
|
|
71
130
|
}
|
|
72
131
|
/** @deprecated Use {@link FindBridgePaths}. */
|
|
73
132
|
export function findBridgePaths(edges, hubs, spokes, opts = {}) {
|
|
@@ -110,17 +169,46 @@ function push(map, key, value) {
|
|
|
110
169
|
else
|
|
111
170
|
map.set(key, [value]);
|
|
112
171
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
172
|
+
/**
|
|
173
|
+
* Path of adjacency edges from `start` to `goal`, bounded in both frontier size and
|
|
174
|
+
* result count. Returns empty paths if none found.
|
|
175
|
+
*
|
|
176
|
+
* WHY THE BOUNDS AND THE CURSOR ARE NOT MICRO-OPTIMISATION. Three properties compounded
|
|
177
|
+
* into an out-of-memory kill on a large schema before the phase could emit anything:
|
|
178
|
+
*
|
|
179
|
+
* 1. Every enqueued state carried a FRESH `Set<string>` and a FRESH path array, allocated
|
|
180
|
+
* per neighbour per dequeued node. On a dense graph with `maxHops` 3 that is
|
|
181
|
+
* O(branching³) live Sets, each holding up to `maxHops + 1` strings.
|
|
182
|
+
* 2. The queue was drained with `Array.shift()`, which is O(n) on a large array, so
|
|
183
|
+
* draining it was quadratic on top of the allocation.
|
|
184
|
+
* 3. Nothing bounded either the queue or the result array.
|
|
185
|
+
*
|
|
186
|
+
* The cursor fixes (2) outright. The caps fix (1) and (3) by refusing to grow past a
|
|
187
|
+
* ceiling and SAYING SO, rather than by silently returning a partial answer. The visited
|
|
188
|
+
* Set is still copied per state — a path-specific visited set is what `pruneCycles` means,
|
|
189
|
+
* and a shared one would wrongly prune valid alternate paths — but it can no longer be
|
|
190
|
+
* copied an unbounded number of times.
|
|
191
|
+
*/
|
|
192
|
+
function bfsPaths(adjacency, start, goal, maxHops, pruneCycles, maxFrontier, maxPaths) {
|
|
116
193
|
if (start === goal)
|
|
117
|
-
return [[]];
|
|
194
|
+
return { paths: [[]], frontierTruncated: false, pathsTruncated: false };
|
|
118
195
|
const queue = [
|
|
119
196
|
{ node: start, pathEdges: [], visited: new Set([start]) },
|
|
120
197
|
];
|
|
198
|
+
// Index cursor instead of Array.shift(): shift() is O(n) on a large array, which made
|
|
199
|
+
// draining the queue quadratic in the number of enqueued states.
|
|
200
|
+
let head = 0;
|
|
121
201
|
const found = [];
|
|
122
|
-
|
|
123
|
-
|
|
202
|
+
let frontierTruncated = false;
|
|
203
|
+
let pathsTruncated = false;
|
|
204
|
+
while (head < queue.length) {
|
|
205
|
+
const { node, pathEdges, visited } = queue[head];
|
|
206
|
+
// Release the slot as we pass it. An index cursor alone keeps every state ever enqueued
|
|
207
|
+
// reachable from the array — including its visited Set — which would trade Array.shift()'s
|
|
208
|
+
// O(n) drain for a retained-memory leak over a long walk. Nulling gives O(1) dequeue AND
|
|
209
|
+
// lets the frontier bound below actually bound live memory.
|
|
210
|
+
queue[head] = undefined;
|
|
211
|
+
head++;
|
|
124
212
|
if (pathEdges.length >= maxHops)
|
|
125
213
|
continue;
|
|
126
214
|
const neighbors = adjacency.get(node) ?? [];
|
|
@@ -130,15 +218,28 @@ function bfsPaths(adjacency, start, goal, maxHops, pruneCycles) {
|
|
|
130
218
|
continue;
|
|
131
219
|
const newPath = [...pathEdges, edge];
|
|
132
220
|
if (nextNode === goal) {
|
|
221
|
+
if (found.length >= maxPaths) {
|
|
222
|
+
pathsTruncated = true;
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
133
225
|
found.push(newPath);
|
|
134
226
|
continue; // don't extend past the goal
|
|
135
227
|
}
|
|
228
|
+
// The live frontier is what is enqueued but not yet expanded. Bounding THAT
|
|
229
|
+
// rather than total enqueues keeps a long, narrow walk working while still
|
|
230
|
+
// refusing to hold an unbounded number of visited-set copies at once.
|
|
231
|
+
if (queue.length - head >= maxFrontier) {
|
|
232
|
+
frontierTruncated = true;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
136
235
|
const nextVisited = new Set(visited);
|
|
137
236
|
nextVisited.add(nextNode);
|
|
138
237
|
queue.push({ node: nextNode, pathEdges: newPath, visited: nextVisited });
|
|
139
238
|
}
|
|
239
|
+
if (pathsTruncated)
|
|
240
|
+
break;
|
|
140
241
|
}
|
|
141
|
-
return found;
|
|
242
|
+
return { paths: found, frontierTruncated, pathsTruncated };
|
|
142
243
|
}
|
|
143
244
|
// ─── Bridge path materialization ────────────────────────────────────────────
|
|
144
245
|
function materializeBridgePath(edgePath, hub, spoke) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FKGraphWalker.js","sourceRoot":"","sources":["../../src/discovery/FKGraphWalker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;
|
|
1
|
+
{"version":3,"file":"FKGraphWalker.js","sourceRoot":"","sources":["../../src/discovery/FKGraphWalker.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,8 @@ export declare class LLMDiscoveryValidator {
|
|
|
26
26
|
* Build rich context for a table including stats from cache
|
|
27
27
|
*/
|
|
28
28
|
private buildTableContext;
|
|
29
|
+
/** Existing indexes on the table as prompt lines, from the introspected schema. */
|
|
30
|
+
private indexHintLines;
|
|
29
31
|
/**
|
|
30
32
|
* Find tables that might be related based on column name patterns
|
|
31
33
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LLMDiscoveryValidator.d.ts","sourceRoot":"","sources":["../../src/discovery/LLMDiscoveryValidator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"LLMDiscoveryValidator.d.ts","sourceRoot":"","sources":["../../src/discovery/LLMDiscoveryValidator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EACL,WAAW,EACX,WAAW,EAGX,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,2BAA2B,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE3E,qBAAa,qBAAqB;IAI9B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,OAAO;IAPjB,OAAO,CAAC,GAAG,CAAU;gBAGX,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,2BAA2B,EACnC,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,gBAAgB,EAC5B,OAAO,EAAE,gBAAgB,EAAE;IAQrC;;OAEG;IACU,0BAA0B,CACrC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,WAAW,EAAE,EAC3B,YAAY,EAAE,WAAW,EAAE,GAC1B,OAAO,CAAC,mBAAmB,CAAC;IAsF/B,0DAA0D;IAC7C,0BAA0B,CACrC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,WAAW,EAAE,EAC3B,YAAY,EAAE,WAAW,EAAE,GAC1B,OAAO,CAAC,mBAAmB,CAAC;IAI/B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiFzB,mFAAmF;IACnF,OAAO,CAAC,cAAc;IAKtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqFzB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAyBjC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAkB/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA4B3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAsC9B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsBxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsBxB;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAoG9B"}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Uses LLM reasoning to validate and refine PK/FK candidates discovered through statistical analysis
|
|
4
4
|
* Processes one table at a time with rich statistical context
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { CreateLLMInstance } from '../utils/llm-factory.js';
|
|
7
|
+
import { BuildIndexHints, FormatIndexHint } from '../utils/index-hints.js';
|
|
8
8
|
export class LLMDiscoveryValidator {
|
|
9
9
|
constructor(driver, config, aiConfig, statsCache, schemas) {
|
|
10
10
|
this.driver = driver;
|
|
@@ -12,12 +12,10 @@ export class LLMDiscoveryValidator {
|
|
|
12
12
|
this.aiConfig = aiConfig;
|
|
13
13
|
this.statsCache = statsCache;
|
|
14
14
|
this.schemas = schemas;
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
this.llm = llm;
|
|
15
|
+
// Resolve the provider name (e.g. 'gemini') to its driver class (e.g. 'GeminiLLM'), as the rest
|
|
16
|
+
// of DBAutoDoc does. Using the raw provider name as the registration key resolved to nothing and
|
|
17
|
+
// left a bare BaseLLM, so every validation call failed.
|
|
18
|
+
this.llm = CreateLLMInstance(aiConfig.provider, aiConfig.apiKey);
|
|
21
19
|
}
|
|
22
20
|
/**
|
|
23
21
|
* Validate PK/FK candidates for a single table using LLM reasoning
|
|
@@ -155,9 +153,15 @@ export class LLMDiscoveryValidator {
|
|
|
155
153
|
TargetTable: targetTable,
|
|
156
154
|
RelatedTables: relatedTables,
|
|
157
155
|
pkCandidates: pkContext,
|
|
158
|
-
fkCandidates: fkContext
|
|
156
|
+
fkCandidates: fkContext,
|
|
157
|
+
ExistingIndexes: this.indexHintLines(schemaName, tableName)
|
|
159
158
|
};
|
|
160
159
|
}
|
|
160
|
+
/** Existing indexes on the table as prompt lines, from the introspected schema. */
|
|
161
|
+
indexHintLines(schemaName, tableName) {
|
|
162
|
+
const table = this.schemas.find(s => s.name === schemaName)?.tables.find(t => t.name === tableName);
|
|
163
|
+
return BuildIndexHints(table).map(FormatIndexHint);
|
|
164
|
+
}
|
|
161
165
|
/**
|
|
162
166
|
* Find tables that might be related based on column name patterns
|
|
163
167
|
*/
|
|
@@ -389,6 +393,13 @@ ${context.RelatedTables
|
|
|
389
393
|
`
|
|
390
394
|
: ''}
|
|
391
395
|
|
|
396
|
+
${context.ExistingIndexes && context.ExistingIndexes.length > 0
|
|
397
|
+
? `### Existing Indexes (declared in the database):
|
|
398
|
+
${context.ExistingIndexes.map(line => `- ${line}`).join('\n')}
|
|
399
|
+
|
|
400
|
+
Indexes are evidence, not proof: a UNIQUE index or PRIMARY KEY on non-null columns strongly supports a PK candidate on exactly those columns; a non-unique index led by an ID-like column often marks a foreign key. "(expression)" is a computed key part.
|
|
401
|
+
`
|
|
402
|
+
: ''}
|
|
392
403
|
### Statistical Analysis Found:
|
|
393
404
|
|
|
394
405
|
**Primary Key Candidates:**
|