AI-powered database documentation generator for SQL Server, MySQL, and PostgreSQL. Analyzes database structure using LLMs to generate intelligent descriptions, discovers missing relationships, generates reference SQL queries, and saves documentation as database metadata.
graph TD
A["CLI / Programmatic API"] --> B["AnalysisOrchestrator"]
B --> C["Database Layer
(Schema Introspection)"]
B --> D["Analysis Engine
(LLM Processing)"]
B --> E["State Manager
(Progress Tracking)"]
B --> F["Guardrails Manager
(Resource Limits)"]
C --> G["SQL Server"]
C --> H["PostgreSQL"]
C --> I["MySQL"]
D --> J["Description Generator"]
D --> K["Relationship Discovery"]
D --> L["Sample Query Generator"]
J --> M["Output Generators"]
M --> N["SQL Extended Properties"]
M --> O["Markdown / HTML / CSV"]
M --> P["Mermaid ERD Diagrams"]
style A fill:#2d6a9f,stroke:#1a4971,color:#fff
style B fill:#7c5295,stroke:#563a6b,color:#fff
style C fill:#2d8659,stroke:#1a5c3a,color:#fff
style D fill:#7c5295,stroke:#563a6b,color:#fff
style E fill:#b8762f,stroke:#8a5722,color:#fff
style F fill:#b8762f,stroke:#8a5722,color:#fff
style M fill:#2d6a9f,stroke:#1a4971,color:#fff
--reanalyze-below-confidence to target low-confidence tables while preserving ground truthadditionalSchemaInfo.json for MemberJunction CodeGen soft FK/PK supportnpm install -g @memberjunction/db-auto-doc
npm install @memberjunction/db-auto-doc
npm install @memberjunction/db-auto-doc --save
DBAutoDoc has been extensively benchmarked across multiple databases and LLM providers. Full details in the research paper.
| Model Configuration | PK F1 | FK F1 | Overall |
|---|---|---|---|
| Gemini 3 Flash / 3.1 Pro | 95.0% | 94.2% | 96.1% (A+) |
| Claude Sonnet 4.6 / Opus 4.6 | 95.0% | 93.0% | 96.1% (A+) |
| GPT-5.4-mini / GPT-5.4 | 89.4% | 77.9% | 87.9% (B+) |
| Database | Tables | PK F1 | FK F1 | Descriptions |
|---|---|---|---|---|
| AdventureWorks | 71 | 95.0% | 94.2% | 99% |
| Chinook | 11 | 95.2% | 95.2% | 100% |
| LousyDB (dark DB) | 20 | 97.6% | 77.2% | 100% |
| Northwind | 13 | 72.7% | 75.0% | 100% |
DBAutoDoc uses a 4-phase pipeline for relationship discovery:
See research/v1/ for the full paper, benchmark results, and comparison scripts:
db-auto-doc init
This interactive wizard will:
config.jsondb-auto-doc analyze
This will:
db-doc-state.jsonGenerate reference SQL queries for AI agent training:
# During analysis (if enabled in config)
db-auto-doc analyze # Automatically generates queries
# Or generate separately from existing state
db-auto-doc generate-queries --from-state ./output/run-1/state.json
# With custom settings
db-auto-doc generate-queries --from-state ./output/run-1/state.json \
--queries-per-table 10 \
--max-execution-time 60000 \
--output-dir ./queries
This generates:
Configuration Options:
{
"analysis": {
"sampleQueryGeneration": {
"enabled": true, // Enable sample query generation
"queriesPerTable": 5, // Number of queries per table
"maxTables": 10, // Max tables to process (0 = all tables)
"tokenBudget": 100000, // Token limit (0 = unlimited)
"maxExecutionTime": 30000, // Query validation timeout (ms)
"includeMultiQueryPatterns": true, // Generate related query patterns
"validateAlignment": true, // Validate alignment between queries
"maxRowsInSample": 10, // Sample result rows to capture
"enableQueryFix": true, // Auto-fix failed queries (default: true)
"maxFixAttempts": 3, // Max fix attempts per query (default: 3)
"enableQueryRefinement": true, // LLM-based result analysis (default: false)
"maxRefinementAttempts": 1 // Max refinement iterations (default: 1)
}
}
}
Query Fix & Refinement:
DBAutoDoc includes two quality control mechanisms to ensure high-quality queries:
1. Query Fix (Error Recovery)
enableQueryFix: true (default: true) - Enable automatic fixesmaxFixAttempts: 3 (default: 3) - Maximum retry attempts per query2. Query Refinement (Quality Improvement)
enableQueryRefinement: false (default: false) - Enable refinement analysismaxRefinementAttempts: 1 (default: 1) - Maximum refinement iterationsProcessing Flow:
Generate SQL
→ Validate (execute against DB)
→ If Failed: Fix (up to maxFixAttempts) → Re-validate
→ If Passed & Refinement Enabled: Refine → Re-validate → Repeat (up to maxRefinementAttempts)
→ Done
Example Configuration:
{
"sampleQueryGeneration": {
"enableQueryFix": true, // Fix broken queries
"maxFixAttempts": 3, // Try up to 3 times
"enableQueryRefinement": true, // Improve working queries
"maxRefinementAttempts": 2 // Up to 2 refinement passes
}
}
Key Configuration Settings:
maxTables: Controls table selection
10 (default) - Generate queries for top 10 most important tables0 - Generate queries for all tables with datatokenBudget: Controls LLM token usage and cost
100000 (default) - Limit to 100K tokens (~$0.50-1.00 with Gemini Flash)0 - Unlimited token budget (useful with maxTables: 0)Example Configurations:
Cost-conscious (default):
{
"maxTables": 10,
"tokenBudget": 100000
}
Medium coverage (~25 tables):
{
"maxTables": 25,
"tokenBudget": 500000
}
Complete coverage (all tables):
{
"maxTables": 0,
"tokenBudget": 0
}
Model Recommendations (based on benchmark results):
modelOverrides config for the precision-critical pruning pass.db-auto-doc export --sql --markdown --html --csv --mermaid --schema-info
This generates:
additionalSchemaInfo.json for CodeGen soft FK/PK supportOptionally apply directly to database:
db-auto-doc export --sql --apply
Export only AI-discovered relationships (exclude hard DB constraints):
db-auto-doc export --schema-info --schema-info-discovered-only --confidence-threshold 70
Transform generated sample queries into MemberJunction metadata format for syncing to the database:
# Basic export
db-auto-doc export-sample-queries \
--input ./output/sample-queries.json \
--output ./metadata/queries/.queries.json
# Export with separate SQL files (uses @file: references)
db-auto-doc export-sample-queries \
--input ./output/sample-queries.json \
--output ./metadata/queries/.queries.json \
--separate-sql-files
# Set category and filter by quality
db-auto-doc export-sample-queries \
--input ./output/sample-queries.json \
--output ./metadata/queries/.queries.json \
--category "Database Documentation" \
--status Approved \
--min-confidence 0.8 \
--validated-only
Key Flags:
--input, -i: Path to sample-queries.json from generate-queries--output, -o: Output path for .queries.json metadata file--separate-sql-files: Write SQL to separate files with @file: references--sql-dir: Directory for SQL files (default: "SQL")--category: Query category for @lookup:Query Categories.Name=...--status: Status to assign (Approved/Pending/Rejected/Expired)--min-confidence: Minimum confidence threshold (0-1)--validated-only: Only export successfully validated queries--append: Append to existing metadata fileAfter Export:
npx mj-sync push ./metadata/queries/This integrates DBAutoDoc-generated queries with MemberJunction's metadata system for use by AI agents like Skip.
db-auto-doc status
Shows:
db-auto-doc analyze --resume ./db-doc-state.json
Resume a previous analysis from a checkpoint state file, useful for:
DBAutoDoc processes tables in dependency order:
Level 0: Users, Products, Categories (no dependencies)
↓
Level 1: Orders (depends on Users), ProductCategories (Products + Categories)
↓
Level 2: OrderItems (depends on Orders + Products)
↓
Level 3: Shipments (depends on OrderItems)
Processing in this order allows child tables to benefit from parent table context.
For legacy databases missing primary/foreign key constraints, DBAutoDoc can:
Triggered automatically when:
Foreign keys require shared exact values. Organic keys (MemberJunction PR #2193) capture the weaker-but-broader condition of shared identity: two columns refer to the same real-world thing once each is canonicalized through its own transformation. That joins far more cross-system data than exact-match FKs -- e.g. the same phone number stored as +1 (555) 123-4567, 5551234567, and 555.123.4567 across HubSpot, Zendesk, and QuickBooks.
This pass is off by default and runs after PK/FK detection. Enable it with organicKeyDetection.enabled: true (it reuses your existing ai provider for both the LLM and embeddings). The pipeline:
BaseEmbeddings) and grouped with agglomerative clustering using an auto-calibrated distance threshold.product_id vs product_category_id) are split apart using the LLM concept tags.Results are written into additionalSchemaInfo.json (see CodeGen Integration) as OrganicKeys entries, which CodeGen upserts into EntityOrganicKey / EntityOrganicKeyRelatedEntity metadata. At runtime, EntityInfo.BuildOrganicKeyViewParams applies each side's own normalization expression when matching records.
Note: Embeddings route through MemberJunction's
BaseEmbeddingsdrivers (OpenAI, Mistral, Azure, Bedrock, Ollama, local), defaulting toOpenAIEmbedding. The detection pass therefore requires an embedding provider with a valid key configured.
DBAutoDoc can generate reference SQL queries for AI agents, solving the query alignment problem where multi-query patterns (summary + detail) have inconsistent filtering logic:
The Problem:
-- Summary query
SELECT COUNT(*) FROM Registrations -- All registrations
-- Detail query
SELECT * FROM Registrations WHERE Status='Attended' -- Only attended
-- Result: Numbers don't match! Bad UX.
The Solution: DBAutoDoc generates "gold standard" reference queries with:
relatedQueryIdsTwo-Prompt Architecture:
This approach prevents JSON truncation issues while maintaining alignment context between related queries.
Use Cases:
After analyzing child tables, DBAutoDoc can detect insights about parent tables and trigger re-analysis:
Level 0: "Persons" → Initially thinks: "General contact information"
↓
Level 1: "Students" table reveals Persons.Type has values: Student, Teacher, Staff
↓
BACKPROPAGATE to Level 0: "Persons" → Revise to: "School personnel with role-based typing"
Analysis stops when:
Provide authoritative, user-supplied documentation that AI analysis must respect. Ground truth descriptions are injected into prompts as AUTHORITATIVE context and are never overwritten by AI analysis or backpropagation.
Configuration:
{
"seedContext": {
"overallPurpose": "E-commerce platform for retail",
"businessDomains": ["Sales", "Inventory", "Users"],
"industryContext": "Retail"
},
"groundTruth": {
"databaseDescription": "Primary transactional database for online store",
"schemas": {
"dbo": { "description": "Core application schema", "businessDomain": "Core" },
"hr": { "description": "Human resources schema", "businessDomain": "HR" }
},
"tables": {
"dbo.Users": {
"description": "Registered user accounts with authentication data",
"notes": "Primary user table - synced from identity provider",
"businessDomain": "Identity",
"columns": {
"Email": { "description": "Primary email for authentication", "notes": "Must be unique" },
"Status": { "description": "Account status: Active, Suspended, Deleted" }
}
}
}
}
}
How it works:
userApproved: true in stateAUTHORITATIVE context to guide analysis--reanalyze-below-confidencebusinessDomain falls back from table → schema if not specified at table levelState is persisted to disk at every phase boundary, not just at the end. If analysis is interrupted, you can resume from the last checkpoint:
Tables and columns marked userApproved: true (via ground truth or manual approval) are protected from modification:
--reanalyze-below-confidenceResume analysis with fine-grained control:
# Resume from a previous run's state file
db-auto-doc analyze --resume ./output/run-1/state.json
# Resume and re-analyze tables with confidence below 70%
db-auto-doc analyze --resume ./state.json --reanalyze-below 0.7
# Resume with a different iteration limit
db-auto-doc analyze --resume ./state.json --max-iterations 20
# Resume with additional iterations (e.g., ran 5 originally, now want 3 more)
db-auto-doc analyze --resume ./state.json --max-iterations 3
The --reanalyze-below flag clears userApproved on non-ground-truth tables whose latest confidence is below the threshold, allowing them to be re-analyzed while protecting authoritative descriptions.
Run just the FK pruning pass on an existing state file, skipping discovery and analysis iterations. Useful when you want to apply a stronger model to clean up FK false positives without re-running the full analysis:
# Run only the FK pruning pass on an existing state
db-auto-doc analyze --resume ./output/run-1/state.json --pruning-only
# Combine with a config that specifies a stronger pruning model
db-auto-doc analyze --resume ./output/run-1/state.json --pruning-only --config ./config-with-pro-pruning.json
Requires --resume pointing to a state file that has already completed discovery and at least one analysis iteration. The pruning pass uses the ai.modelOverrides.fkPruning config to select a potentially stronger model (e.g., Gemini Pro, Claude Opus) for the precision-critical FK filtering.
| Flag | Short | Description |
|---|---|---|
--config |
-c |
Path to config file (default: ./config.json) |
--resume |
-r |
Resume from an existing state file |
--max-iterations |
-n |
Override max iterations from config |
--reanalyze-below |
Re-analyze tables with confidence below threshold (0-1) | |
--pruning-only |
Skip discovery/iterations, run only PK/FK pruning (requires --resume) |
The prune command runs PK/FK pruning on an existing state file without re-running analysis. It provides interactive confirmation before applying changes.
# Interactive mode (shows proposals, asks for confirmation)
db-auto-doc prune --state ./output/run-1/state.json --config ./config.json
# Silent mode (applies all pruning automatically)
db-auto-doc prune --state ./output/run-1/state.json --config ./config.json --silent
# PK-only or FK-only pruning
db-auto-doc prune --state ./output/run-1/state.json --config ./config.json --pk-only
db-auto-doc prune --state ./output/run-1/state.json --config ./config.json --fk-only
| Flag | Description |
|---|---|
--state |
Path to existing state.json file (required) |
--config |
Path to config file with AI settings (required) |
--silent |
Skip interactive confirmation |
--pk-only |
Only prune primary keys |
--fk-only |
Only prune foreign keys |
DBAutoDoc automatically emits additionalSchemaInfo.json in every analysis run folder. This file is compatible with MemberJunction CodeGen's soft FK/PK system, allowing AI-discovered relationships to be fed back into the metadata layer.
Output format (matches CodeGen's additionalSchemaInfo.json):
{
"Schemas": [
{
"name": "CRM",
"entityNamePrefix": "CRM: ",
"entityNameSuffix": "",
"description": "Customer relationship management tables"
},
{
"name": "ACCOUNTING",
"entityNamePrefix": "Accounting: ",
"entityNameSuffix": "",
"description": "Financial and accounting tables"
}
],
"CRM": [
{
"TableName": "CUSTOMER",
"PrimaryKey": [
{ "FieldName": "CUSTOMER_ID", "Description": "AI-discovered primary key (confidence: 95%)" }
]
},
{
"TableName": "ORDER",
"ForeignKeys": [
{
"FieldName": "CUSTOMER_ID",
"SchemaName": "CRM",
"RelatedTable": "CUSTOMER",
"RelatedField": "CUSTOMER_ID",
"Description": "AI-discovered relationship (confidence: 88%)"
}
]
}
]
}
The top-level Schemas array provides entity naming recommendations for CodeGen. For multi-schema databases, each schema gets a prefix to prevent entity name collisions when CodeGen creates MemberJunction entities.
Prefix generation rules:
"CRM: ")AI_COMMERCE_CONTEXT → "AI Commerce Context: ")ACCOUNTING → "Accounting: ")CodeGen reads the Schemas array and applies prefixes to SchemaInfo records, which are then prepended to entity display names during entity creation. This ensures entities like CRM.CUSTOMER and SALES.CUSTOMER become "CRM: Customer" and "Sales: Customer" instead of colliding.
Data sources:
--schema-info-discovered-only)Export options:
--schema-info -- Generate the file--schema-info-discovered-only -- Only include AI-discovered keys (exclude hard DB constraints)--schema-info-confirmed-only -- Only include confirmed candidates (exclude unvalidated)--confidence-threshold N -- Minimum confidence score for discovered keysUsage with CodeGen:
additionalSchemaInfo.json to your MJ projectcodeGen.additionalSchemaInfo path in mj.config.cjsMulti-level resource controls ensure analysis stays within bounds:
Run-Level Limits:
maxTokensPerRun: Total token budget for entire analysismaxDurationSeconds: Maximum wall-clock timemaxCostDollars: Maximum AI costPhase-Level Limits:
maxTokensPerPhase.discovery: Budget for relationship discoverymaxTokensPerPhase.analysis: Budget for description generationmaxTokensPerPhase.sanityChecks: Budget for validationIteration-Level Limits:
maxTokensPerIteration: Per-iteration token capmaxIterationDurationSeconds: Per-iteration time limitWarning Thresholds:
For each column, DBAutoDoc collects:
This rich context enables AI to make accurate inferences.
{
"version": "1.0.0",
"database": {
"provider": "sqlserver",
"host": "localhost",
"database": "MyDatabase",
"user": "sa",
"password": "YourPassword",
"encrypt": true,
"trustServerCertificate": false
},
"ai": {
"provider": "openai",
"model": "gpt-5.4-mini",
"apiKey": "sk-...",
"temperature": 0.1,
"maxTokens": 8000,
"effortLevel": 50
},
"analysis": {
"cardinalityThreshold": 20,
"sampleSize": 10,
"includeStatistics": true,
"includePatternAnalysis": true,
"convergence": {
"maxIterations": 50,
"stabilityWindow": 2,
"confidenceThreshold": 0.85
},
"backpropagation": {
"enabled": true,
"maxDepth": 3
},
"sanityChecks": {
"dependencyLevel": true,
"schemaLevel": true,
"crossSchema": true
},
"sampleQueryGeneration": {
"enabled": true,
"queriesPerTable": 5,
"maxExecutionTime": 30000,
"includeMultiQueryPatterns": true,
"validateAlignment": true,
"tokenBudget": 100000,
"maxRowsInSample": 10,
"enableQueryFix": true,
"maxFixAttempts": 3,
"enableQueryRefinement": true,
"maxRefinementAttempts": 1
},
"guardrails": {
"enabled": true,
"stopOnExceeded": true,
"maxTokensPerRun": 250000,
"maxDurationSeconds": 3600,
"maxCostDollars": 50,
"maxTokensPerPhase": {
"discovery": 100000,
"analysis": 150000,
"sanityChecks": 50000
},
"maxTokensPerIteration": 50000,
"maxIterationDurationSeconds": 600,
"warnThresholds": {
"tokenPercentage": 80,
"durationPercentage": 80,
"costPercentage": 80,
"iterationTokenPercentage": 85,
"phaseTokenPercentage": 85
}
},
"relationshipDiscovery": {
"enabled": true,
"triggers": {
"runOnMissingPKs": true,
"runOnInsufficientFKs": true,
"fkDeficitThreshold": 0.4
},
"tokenBudget": {
"ratioOfTotal": 0.4
},
"confidence": {
"primaryKeyMinimum": 0.7,
"foreignKeyMinimum": 0.6,
"llmValidationThreshold": 0.8
},
"sampling": {
"maxRowsPerTable": 1000,
"valueOverlapSampleSize": 100,
"statisticalSignificance": 100,
"compositeKeyMaxColumns": 3
},
"patterns": {
"primaryKeyNames": ["^id$", ".*_id$", "^pk_.*", ".*_key$"],
"foreignKeyNames": [".*_id$", ".*_fk$", "^fk_.*"]
},
"llmValidation": {
"enabled": true,
"batchSize": 10
},
"backpropagation": {
"enabled": true,
"maxIterations": 5
}
},
"organicKeyDetection": {
"enabled": false,
"clusteringSensitivity": "balanced",
"minClusterSize": 2,
"minDistinctTables": 2,
"sampleValueCount": 5,
"refinementConcurrency": 4,
"maxRefinementRetries": 2,
"embedding": {
"provider": "openai",
"model": "text-embedding-3-small"
}
}
},
"output": {
"stateFile": "./db-doc-state.json",
"outputDir": "./output",
"sqlFile": "./output/add-descriptions.sql",
"markdownFile": "./output/database-documentation.md"
},
"schemas": {
"exclude": ["sys", "INFORMATION_SCHEMA"]
},
"tables": {
"exclude": ["sysdiagrams", "__MigrationHistory"]
}
}
{
"version": "1.0.0",
"database": {
"provider": "postgresql",
"host": "localhost",
"port": 5432,
"database": "mydatabase",
"user": "postgres",
"password": "YourPassword",
"ssl": false
},
"ai": {
"provider": "openai",
"model": "gpt-5.4-mini",
"apiKey": "sk-...",
"temperature": 0.1,
"maxTokens": 8000
},
"analysis": {
"cardinalityThreshold": 20,
"sampleSize": 10,
"includeStatistics": true,
"guardrails": {
"enabled": true,
"maxTokensPerRun": 250000
}
},
"output": {
"stateFile": "./db-doc-state.json",
"outputDir": "./output",
"sqlFile": "./output/add-descriptions.sql",
"markdownFile": "./output/database-documentation.md"
},
"schemas": {
"exclude": ["pg_catalog", "information_schema"]
}
}
{
"version": "1.0.0",
"database": {
"provider": "mysql",
"host": "localhost",
"port": 3306,
"database": "mydatabase",
"user": "root",
"password": "YourPassword"
},
"ai": {
"provider": "openai",
"model": "gpt-5.4-mini",
"apiKey": "sk-...",
"temperature": 0.1,
"maxTokens": 8000
},
"analysis": {
"cardinalityThreshold": 20,
"sampleSize": 10,
"includeStatistics": true,
"guardrails": {
"enabled": true,
"maxTokensPerRun": 250000
}
},
"output": {
"stateFile": "./db-doc-state.json",
"outputDir": "./output",
"sqlFile": "./output/add-descriptions.sql",
"markdownFile": "./output/database-documentation.md"
},
"schemas": {
"exclude": ["mysql", "information_schema", "performance_schema", "sys"]
}
}
{
"ai": {
"retry": {
"maxRetries": 5,
"initialDelayMs": 30000,
"maxDelayMs": 480000,
"backoffMultiplier": 2
},
"rateLimits": {
"requestsPerMinute": 60,
"maxParallelRequests": 1
}
}
}
Handles 429 (rate limit) and transient network errors with exponential backoff. Configure based on your API provider's limits.
Use different models for different pipeline phases. A cheaper/faster model for bulk analysis, a stronger model for precision-critical pruning:
{
"ai": {
"provider": "gemini",
"model": "gemini-3-flash-preview",
"modelOverrides": {
"fkPruning": {
"model": "gemini-3.1-pro-preview",
"temperature": 0.05,
"maxTokens": 16000
},
"pkPruning": {
"model": "gemini-3.1-pro-preview",
"temperature": 0.05
}
}
}
}
DBAutoDoc integrates with MemberJunction's AI provider system. Supported providers:
| Config Provider | Driver Class | Description |
|---|---|---|
gemini (default) |
GeminiLLM | Google Gemini |
openai |
OpenAILLM | OpenAI |
anthropic |
AnthropicLLM | Anthropic Claude |
groq |
GroqLLM | Groq |
mistral |
MistralLLM | Mistral AI |
vertex |
VertexLLM | Google Vertex AI |
azure |
AzureLLM | Azure OpenAI |
cerebras |
CerebrasLLM | Cerebras |
openrouter |
OpenRouterLLM | OpenRouter (multi-model) |
xai |
xAILLM | xAI (Grok) |
bedrock |
BedrockLLM | AWS Bedrock |
{
"provider": "gemini",
"model": "gemini-3-flash-preview",
"apiKey": "..."
}
{
"provider": "openai",
"model": "gpt-5.4-mini",
"apiKey": "sk-..."
}
{
"provider": "anthropic",
"model": "claude-sonnet-4-6",
"apiKey": "sk-ant-..."
}
{
"provider": "groq",
"model": "llama-4-scout-17b-16e-instruct",
"apiKey": "gsk_..."
}
The db-doc-state.json file tracks:
Each description has an iteration history:
{
"descriptionIterations": [
{
"description": "Initial hypothesis...",
"reasoning": "Based on column names...",
"generatedAt": "2024-01-15T10:00:00Z",
"modelUsed": "gpt-4",
"confidence": 0.75,
"triggeredBy": "initial"
},
{
"description": "Revised hypothesis...",
"reasoning": "Child table analysis revealed...",
"generatedAt": "2024-01-15T10:05:00Z",
"modelUsed": "gpt-4",
"confidence": 0.92,
"triggeredBy": "backpropagation",
"changedFrom": "Initial hypothesis..."
}
]
}
DBAutoDoc can be used as a library with a comprehensive programmatic API:
import { DBAutoDocAPI } from '@memberjunction/db-auto-doc';
const api = new DBAutoDocAPI();
// Analyze database
const result = await api.analyze({
database: {
provider: 'sqlserver',
host: 'localhost',
database: 'MyDB',
user: 'sa',
password: 'password'
},
ai: {
provider: 'openai',
model: 'gpt-4-turbo-preview',
apiKey: 'sk-...'
},
analysis: {
convergence: { maxIterations: 10 },
guardrails: { maxTokensPerRun: 100000 }
},
output: {
outputDir: './output'
},
onProgress: (message, data) => {
console.log(message, data);
}
});
// Resume from state file
const resumed = await api.resume('./db-doc-state.json', {
analysis: {
convergence: { maxIterations: 20 }
}
});
// Export documentation
const exported = await api.export('./db-doc-state.json', {
formats: ['sql', 'markdown', 'html', 'csv', 'mermaid'],
outputDir: './docs',
applyToDatabase: true
});
// Get analysis status
const status = await api.getStatus('./db-doc-state.json');
console.log('Progress:', status.progress);
console.log('Tokens used:', status.metrics.totalTokens);
console.log('Estimated cost:', status.metrics.estimatedCost);
import {
ConfigLoader,
DatabaseConnection,
Introspector,
TopologicalSorter,
StateManager,
PromptEngine,
AnalysisEngine,
GuardrailsManager,
SQLGenerator,
MarkdownGenerator,
HTMLGenerator,
CSVGenerator,
MermaidGenerator,
AdditionalSchemaInfoGenerator
} from '@memberjunction/db-auto-doc';
// Load config
const config = await ConfigLoader.load('./config.json');
// Connect to database
const db = new DatabaseConnection(config.database);
await db.connect();
// Introspect
const driver = db.getDriver();
const introspector = new Introspector(driver);
const schemas = await introspector.getSchemas(config.schemas, config.tables);
// Initialize analysis components
const promptEngine = new PromptEngine(config.ai, './prompts');
await promptEngine.initialize();
const stateManager = new StateManager(config.output.stateFile);
const state = stateManager.createInitialState(config.database.database, config.database.server);
state.schemas = schemas;
const guardrails = new GuardrailsManager(config.analysis.guardrails);
const iterationTracker = new IterationTracker();
// Run analysis
const analysisEngine = new AnalysisEngine(config, promptEngine, stateManager, iterationTracker);
// ... custom analysis workflow
// Generate outputs
const sqlGen = new SQLGenerator();
const sql = sqlGen.generate(state, { approvedOnly: false });
const mdGen = new MarkdownGenerator();
const markdown = mdGen.generate(state);
const htmlGen = new HTMLGenerator();
const html = htmlGen.generate(state, { confidenceThreshold: 0.7 });
const csvGen = new CSVGenerator();
const { tables, columns } = csvGen.generate(state);
const mermaidGen = new MermaidGenerator();
const erdDiagram = mermaidGen.generate(state);
const erdHtml = mermaidGen.generateHtml(state);
const schemaInfoGen = new AdditionalSchemaInfoGenerator();
const schemaInfo = schemaInfoGen.generate(state, {
discoveredOnly: true, // Only AI-discovered keys
confidenceThreshold: 70, // Minimum confidence
confirmedOnly: true // Only LLM-validated candidates
});
Typical costs (will vary by database size and complexity):
| Database Size | Tables | Iterations | Tokens | Cost (Gemini Flash) | Cost (Sonnet 4.6) |
|---|---|---|---|---|---|
| Small | 10-20 | 2-3 | ~50K | $0.50 | $0.02 |
| Medium | 50-100 | 3-5 | ~200K | $2.00 | $0.08 |
| Large | 200+ | 5-8 | ~500K | $5.00 | $0.20 |
| Enterprise | 500+ | 8-15 | ~1.5M | $15.00 | $0.60 |
With Relationship Discovery: Add 25-40% to token/cost estimates for databases with missing constraints.
With Sample Query Generation (5 queries/table, Gemini Flash):
| Database Size | Tables | Additional Tokens | Additional Cost |
|---|---|---|---|
| Small | 10-20 | ~100K | $0.50-1.00 |
| Medium | 50-100 | ~500K | $2.50-5.00 |
| Large | 200+ | ~2M | $10-20 |
Note: Sample query generation uses ~6× more API calls than description generation (planning + individual SQL generation for each query), adding ~50% to total token usage.
Guardrails help control costs by setting hard limits on token usage and runtime.
--confidence-threshold to only apply high-confidence descriptionsConfiguration:
enableQueryFix: true, default) - Auto-fixes broken queries (up to 3 attempts)enableQueryRefinement: true, optional) - LLM improves working queriesmaxRefinementAttempts: 2) - More iterations = better quality but higher costQuality Control:
7. Enable alignment validation - Ensures related queries use consistent filtering logic
8. Validate execution - Set maxExecutionTime to test queries actually run (default: 30s)
9. Review refinement results - Check wasRefined flag and refinementHistory in output
10. Compare fix vs refinement - Fix errors are in fixHistory, improvements in refinementHistory
Usage:
11. Generate separately - Use generate-queries command on existing state to avoid re-running full analysis
12. Export to metadata - Use export-sample-queries to sync queries to MemberJunction
13. Use for few-shot prompting - Include in AI agent system prompts as examples
14. Focus on complex tables - Skip simple lookup tables to save costs
15. Document patterns - Use generated queries to document common query patterns for your domain
Understanding Results:
validated: true = Query executes successfullyfixAttempts: 0 = Query worked on first tryfixAttempts: 2, validated: true = Query fixed after 2 attemptswasRefined: true = Query was improved after initial successrefinementAttempts: 2 = Query went through 2 refinement passesmaxIterations in configconfidenceThresholdmaxTokens per prompt--resume to continue from checkpointComprehensive documentation is available in the docs/ folder:
DBAutoDoc uses a sophisticated multi-phase architecture:
See ARCHITECTURE.md for comprehensive architecture documentation, including:
DBAutoDoc is part of the MemberJunction project. Contributions welcome!
MIT
Located in /Demos/LousyDB/, this demo showcases Relationship Discovery capabilities on a realistic legacy database:
cst, ord, pmt)A, T, P)Perfect for testing DBAutoDoc's ability to reverse-engineer poorly-documented databases.
See /Demos/LousyDB/README.md for details and testing instructions.