- Introduce Domain and DomainTable models for logical grouping of tables. - Implement export and import functionality for domains in DrawDB format. - Update template execution modes to include domain processing. - Enhance documentation for domain features and usage.
150 lines
5.1 KiB
Markdown
150 lines
5.1 KiB
Markdown
# Domains and DrawDB Areas Integration
|
|
|
|
## Overview
|
|
|
|
Domains provide a way to organize tables from potentially multiple schemas into logical business groupings. When working with DrawDB format, domains are automatically imported/exported as **Subject Areas** - a native DrawDB feature for visually grouping tables.
|
|
|
|
## How It Works
|
|
|
|
### Writing Domains to DrawDB (Export)
|
|
|
|
When you export a database with domains to DrawDB format:
|
|
|
|
1. **Schema Areas** are created automatically for each schema (existing behavior)
|
|
2. **Domain Areas** are created for each domain, calculated based on the positions of the tables they contain
|
|
3. The domain area bounds are automatically calculated to encompass all its tables with a small padding
|
|
|
|
```go
|
|
// Example: Creating a domain and exporting to DrawDB
|
|
db := models.InitDatabase("mydb")
|
|
|
|
// Create an "authentication" domain
|
|
authDomain := models.InitDomain("authentication")
|
|
authDomain.Tables = append(authDomain.Tables,
|
|
models.InitDomainTable("users", "public"),
|
|
models.InitDomainTable("roles", "public"),
|
|
models.InitDomainTable("permissions", "public"),
|
|
)
|
|
db.Domains = append(db.Domains, authDomain)
|
|
|
|
// Create a "financial" domain spanning multiple schemas
|
|
finDomain := models.InitDomain("financial")
|
|
finDomain.Tables = append(finDomain.Tables,
|
|
models.InitDomainTable("accounts", "public"),
|
|
models.InitDomainTable("transactions", "public"),
|
|
models.InitDomainTable("ledger", "finance"), // Different schema!
|
|
)
|
|
db.Domains = append(db.Domains, finDomain)
|
|
|
|
// Write to DrawDB - domains become subject areas
|
|
writer := drawdb.NewWriter(&writers.WriterOptions{
|
|
OutputPath: "schema.json",
|
|
})
|
|
writer.WriteDatabase(db)
|
|
```
|
|
|
|
The resulting DrawDB JSON will have Subject Areas for both:
|
|
- "authentication" area containing the auth tables
|
|
- "financial" area containing the financial tables from both schemas
|
|
|
|
### Reading Domains from DrawDB (Import)
|
|
|
|
When you import a DrawDB file with Subject Areas:
|
|
|
|
1. **Subject Areas** are automatically converted to **Domains**
|
|
2. Tables are assigned to a domain if they fall within the area's visual bounds
|
|
3. Table references include both the table name and schema name
|
|
|
|
```go
|
|
// Example: Reading DrawDB with areas
|
|
reader := drawdb.NewReader(&readers.ReaderOptions{
|
|
FilePath: "schema.json",
|
|
})
|
|
|
|
db, err := reader.ReadDatabase()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Access domains
|
|
for _, domain := range db.Domains {
|
|
fmt.Printf("Domain: %s\n", domain.Name)
|
|
for _, domainTable := range domain.Tables {
|
|
fmt.Printf(" - %s.%s\n", domainTable.SchemaName, domainTable.TableName)
|
|
|
|
// Access the actual table reference if loaded
|
|
if domainTable.RefTable != nil {
|
|
fmt.Printf(" Description: %s\n", domainTable.RefTable.Description)
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Domain Structure
|
|
|
|
```go
|
|
type Domain struct {
|
|
Name string // Domain name (e.g., "authentication", "user_data")
|
|
Description string // Optional human-readable description
|
|
Tables []*DomainTable // Tables belonging to this domain
|
|
Comment string // Optional comment
|
|
Metadata map[string]any // Extensible metadata
|
|
Sequence uint // Ordering hint
|
|
}
|
|
|
|
type DomainTable struct {
|
|
TableName string // Table name
|
|
SchemaName string // Schema containing the table
|
|
Sequence uint // Ordering hint
|
|
RefTable *Table // Pointer to actual table (in-memory only, not serialized)
|
|
}
|
|
```
|
|
|
|
## Multi-Schema Domains
|
|
|
|
One of the key features of domains is that they can span multiple schemas:
|
|
|
|
```
|
|
Domain: "user_data"
|
|
├── public.users
|
|
├── public.profiles
|
|
├── public.user_preferences
|
|
├── auth.user_sessions
|
|
└── auth.mfa_devices
|
|
```
|
|
|
|
This allows you to organize related tables even when they're stored in different schemas.
|
|
|
|
## Visual Organization in DrawDB
|
|
|
|
When viewing the exported DrawDB file in DrawDB Editor:
|
|
|
|
1. **Schema areas** appear in one color (original behavior)
|
|
2. **Domain areas** appear in a different color
|
|
3. Domain area bounds are calculated to fit all contained tables
|
|
4. Areas can overlap - a table can visually belong to multiple areas
|
|
|
|
## Integration with Other Formats
|
|
|
|
Currently, domain/area integration is implemented for DrawDB format.
|
|
|
|
To implement similar functionality for other formats:
|
|
|
|
1. Identify if the format has a native grouping/area feature
|
|
2. Add conversion logic in the reader to map format areas → Domain model
|
|
3. Add conversion logic in the writer to map Domain model → format areas
|
|
|
|
Example formats that could support domains:
|
|
- **DBML**: Could use DBML's `TableGroup` feature
|
|
- **DrawDB**: ✅ Already implemented (Subject Areas)
|
|
- **GraphQL**: Could use schema directives
|
|
- **Custom formats**: Implement as needed
|
|
|
|
## Tips and Best Practices
|
|
|
|
1. **Keep domains focused**: Each domain should represent a distinct business area
|
|
2. **Document purposes**: Use Description and Comment fields to explain each domain
|
|
3. **Use meaningful names**: Domain names should clearly reflect their purpose
|
|
4. **Maintain schema consistency**: Keep related tables together in the same schema when possible
|
|
5. **Use metadata**: Store tool-specific information in the Metadata field
|