So far so good
Some checks are pending
CI / Test (1.23) (push) Waiting to run
CI / Test (1.24) (push) Waiting to run
CI / Test (1.25) (push) Waiting to run
CI / Lint (push) Waiting to run
CI / Build (push) Waiting to run

This commit is contained in:
2025-12-16 18:10:40 +02:00
parent b9650739bf
commit 7c7054d2e2
44 changed files with 27029 additions and 48 deletions

199
pkg/models/flatview.go Normal file
View File

@@ -0,0 +1,199 @@
package models
import "fmt"
// =============================================================================
// Flat/Denormalized Views - Flattened structures with fully qualified names
// =============================================================================
// FlatColumn represents a column with full context in a single structure
type FlatColumn struct {
DatabaseName string `json:"database_name" yaml:"database_name" xml:"database_name"`
SchemaName string `json:"schema_name" yaml:"schema_name" xml:"schema_name"`
TableName string `json:"table_name" yaml:"table_name" xml:"table_name"`
ColumnName string `json:"column_name" yaml:"column_name" xml:"column_name"`
FullyQualifiedName string `json:"fully_qualified_name" yaml:"fully_qualified_name" xml:"fully_qualified_name"` // database.schema.table.column
Type string `json:"type" yaml:"type" xml:"type"`
Length int `json:"length,omitempty" yaml:"length,omitempty" xml:"length,omitempty"`
Precision int `json:"precision,omitempty" yaml:"precision,omitempty" xml:"precision,omitempty"`
Scale int `json:"scale,omitempty" yaml:"scale,omitempty" xml:"scale,omitempty"`
NotNull bool `json:"not_null" yaml:"not_null" xml:"not_null"`
Default any `json:"default,omitempty" yaml:"default,omitempty" xml:"default,omitempty"`
AutoIncrement bool `json:"auto_increment" yaml:"auto_increment" xml:"auto_increment"`
IsPrimaryKey bool `json:"is_primary_key" yaml:"is_primary_key" xml:"is_primary_key"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
}
// ToFlatColumns converts a Database to a slice of FlatColumns
func (d *Database) ToFlatColumns() []*FlatColumn {
flatColumns := make([]*FlatColumn, 0)
for _, schema := range d.Schemas {
for _, table := range schema.Tables {
for _, column := range table.Columns {
flatColumns = append(flatColumns, &FlatColumn{
DatabaseName: d.Name,
SchemaName: schema.Name,
TableName: table.Name,
ColumnName: column.Name,
FullyQualifiedName: fmt.Sprintf("%s.%s.%s.%s", d.Name, schema.Name, table.Name, column.Name),
Type: column.Type,
Length: column.Length,
Precision: column.Precision,
Scale: column.Scale,
NotNull: column.NotNull,
Default: column.Default,
AutoIncrement: column.AutoIncrement,
IsPrimaryKey: column.IsPrimaryKey,
Description: column.Description,
Comment: column.Comment,
})
}
}
}
return flatColumns
}
// FlatTable represents a table with full context
type FlatTable struct {
DatabaseName string `json:"database_name" yaml:"database_name" xml:"database_name"`
SchemaName string `json:"schema_name" yaml:"schema_name" xml:"schema_name"`
TableName string `json:"table_name" yaml:"table_name" xml:"table_name"`
FullyQualifiedName string `json:"fully_qualified_name" yaml:"fully_qualified_name" xml:"fully_qualified_name"` // database.schema.table
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
Tablespace string `json:"tablespace,omitempty" yaml:"tablespace,omitempty" xml:"tablespace,omitempty"`
ColumnCount int `json:"column_count" yaml:"column_count" xml:"column_count"`
ConstraintCount int `json:"constraint_count" yaml:"constraint_count" xml:"constraint_count"`
IndexCount int `json:"index_count" yaml:"index_count" xml:"index_count"`
}
// ToFlatTables converts a Database to a slice of FlatTables
func (d *Database) ToFlatTables() []*FlatTable {
flatTables := make([]*FlatTable, 0)
for _, schema := range d.Schemas {
for _, table := range schema.Tables {
flatTables = append(flatTables, &FlatTable{
DatabaseName: d.Name,
SchemaName: schema.Name,
TableName: table.Name,
FullyQualifiedName: fmt.Sprintf("%s.%s.%s", d.Name, schema.Name, table.Name),
Description: table.Description,
Comment: table.Comment,
Tablespace: table.Tablespace,
ColumnCount: len(table.Columns),
ConstraintCount: len(table.Constraints),
IndexCount: len(table.Indexes),
})
}
}
return flatTables
}
// FlatConstraint represents a constraint with full context
type FlatConstraint struct {
DatabaseName string `json:"database_name" yaml:"database_name" xml:"database_name"`
SchemaName string `json:"schema_name" yaml:"schema_name" xml:"schema_name"`
TableName string `json:"table_name" yaml:"table_name" xml:"table_name"`
ConstraintName string `json:"constraint_name" yaml:"constraint_name" xml:"constraint_name"`
FullyQualifiedName string `json:"fully_qualified_name" yaml:"fully_qualified_name" xml:"fully_qualified_name"` // database.schema.table.constraint
Type ConstraintType `json:"type" yaml:"type" xml:"type"`
Columns []string `json:"columns" yaml:"columns" xml:"columns"`
Expression string `json:"expression,omitempty" yaml:"expression,omitempty" xml:"expression,omitempty"`
ReferencedTable string `json:"referenced_table,omitempty" yaml:"referenced_table,omitempty" xml:"referenced_table,omitempty"`
ReferencedSchema string `json:"referenced_schema,omitempty" yaml:"referenced_schema,omitempty" xml:"referenced_schema,omitempty"`
ReferencedColumns []string `json:"referenced_columns,omitempty" yaml:"referenced_columns,omitempty" xml:"referenced_columns,omitempty"`
ReferencedFQN string `json:"referenced_fqn,omitempty" yaml:"referenced_fqn,omitempty" xml:"referenced_fqn,omitempty"` // Fully qualified reference
OnDelete string `json:"on_delete,omitempty" yaml:"on_delete,omitempty" xml:"on_delete,omitempty"`
OnUpdate string `json:"on_update,omitempty" yaml:"on_update,omitempty" xml:"on_update,omitempty"`
}
// ToFlatConstraints converts a Database to a slice of FlatConstraints
func (d *Database) ToFlatConstraints() []*FlatConstraint {
flatConstraints := make([]*FlatConstraint, 0)
for _, schema := range d.Schemas {
for _, table := range schema.Tables {
for _, constraint := range table.Constraints {
fc := &FlatConstraint{
DatabaseName: d.Name,
SchemaName: schema.Name,
TableName: table.Name,
ConstraintName: constraint.Name,
FullyQualifiedName: fmt.Sprintf("%s.%s.%s.%s", d.Name, schema.Name, table.Name, constraint.Name),
Type: constraint.Type,
Columns: constraint.Columns,
Expression: constraint.Expression,
ReferencedTable: constraint.ReferencedTable,
ReferencedSchema: constraint.ReferencedSchema,
ReferencedColumns: constraint.ReferencedColumns,
OnDelete: constraint.OnDelete,
OnUpdate: constraint.OnUpdate,
}
// Build fully qualified reference name for foreign keys
if constraint.Type == ForeignKeyConstraint && constraint.ReferencedTable != "" {
fc.ReferencedFQN = fmt.Sprintf("%s.%s.%s", d.Name, constraint.ReferencedSchema, constraint.ReferencedTable)
}
flatConstraints = append(flatConstraints, fc)
}
}
}
return flatConstraints
}
// FlatRelationship represents a relationship with full context
type FlatRelationship struct {
DatabaseName string `json:"database_name" yaml:"database_name" xml:"database_name"`
RelationshipName string `json:"relationship_name" yaml:"relationship_name" xml:"relationship_name"`
Type RelationType `json:"type" yaml:"type" xml:"type"`
FromFQN string `json:"from_fqn" yaml:"from_fqn" xml:"from_fqn"` // database.schema.table
ToFQN string `json:"to_fqn" yaml:"to_fqn" xml:"to_fqn"` // database.schema.table
FromTable string `json:"from_table" yaml:"from_table" xml:"from_table"`
FromSchema string `json:"from_schema" yaml:"from_schema" xml:"from_schema"`
ToTable string `json:"to_table" yaml:"to_table" xml:"to_table"`
ToSchema string `json:"to_schema" yaml:"to_schema" xml:"to_schema"`
ForeignKey string `json:"foreign_key" yaml:"foreign_key" xml:"foreign_key"`
ThroughTableFQN string `json:"through_table_fqn,omitempty" yaml:"through_table_fqn,omitempty" xml:"through_table_fqn,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
}
// ToFlatRelationships converts a Database to a slice of FlatRelationships
func (d *Database) ToFlatRelationships() []*FlatRelationship {
flatRelationships := make([]*FlatRelationship, 0)
for _, schema := range d.Schemas {
for _, table := range schema.Tables {
for _, relationship := range table.Relationships {
fr := &FlatRelationship{
DatabaseName: d.Name,
RelationshipName: relationship.Name,
Type: relationship.Type,
FromFQN: fmt.Sprintf("%s.%s.%s", d.Name, relationship.FromSchema, relationship.FromTable),
ToFQN: fmt.Sprintf("%s.%s.%s", d.Name, relationship.ToSchema, relationship.ToTable),
FromTable: relationship.FromTable,
FromSchema: relationship.FromSchema,
ToTable: relationship.ToTable,
ToSchema: relationship.ToSchema,
ForeignKey: relationship.ForeignKey,
Description: relationship.Description,
}
// Add through table FQN for many-to-many relationships
if relationship.ThroughTable != "" {
fr.ThroughTableFQN = fmt.Sprintf("%s.%s.%s", d.Name, relationship.ThroughSchema, relationship.ThroughTable)
}
flatRelationships = append(flatRelationships, fr)
}
}
}
return flatRelationships
}

6
pkg/models/interface.go Normal file
View File

@@ -0,0 +1,6 @@
package models
// SQLNamer interface for types that can provide a normalized sql name
type SQLNamer interface {
SQLName() string
}

View File

@@ -1,5 +1,7 @@
package models
import "strings"
type DatabaseType string
const (
@@ -11,24 +13,39 @@ const (
// Database represents the complete database schema
type Database struct {
Name string `json:"name" yaml:"name"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
Schemas []*Schema `json:"schemas" yaml:"schemas" xml:"schemas"`
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
DatabaseType DatabaseType `json:"database_type,omitempty" yaml:"database_type,omitempty" xml:"database_type,omitempty"`
DatabaseVersion string `json:"database_version,omitempty" yaml:"database_version,omitempty" xml:"database_version,omitempty"`
SourceFormat string `json:"source_format,omitempty" yaml:"source_format,omitempty" xml:"source_format,omitempty"` //Source Format of the database.
}
// SQLNamer returns the database name in lowercase
func (d *Database) SQLName() string {
return strings.ToLower(d.Name)
}
type Schema struct {
Name string `json:"name" yaml:"name" xml:"name"`
Tables []*Table `json:"tables" yaml:"tables" xml:"-"`
Owner string `json:"owner" yaml:"owner" xml:"owner"`
Permissions map[string]string `json:"permissions,omitempty" yaml:"permissions,omitempty" xml:"-"`
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty" yaml:"metadata,omitempty" xml:"-"`
Scripts []*Script `json:"scripts,omitempty" yaml:"scripts,omitempty" xml:"scripts,omitempty"`
Name string `json:"name" yaml:"name" xml:"name"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
Tables []*Table `json:"tables" yaml:"tables" xml:"-"`
Owner string `json:"owner" yaml:"owner" xml:"owner"`
Permissions map[string]string `json:"permissions,omitempty" yaml:"permissions,omitempty" xml:"-"`
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
Metadata map[string]any `json:"metadata,omitempty" yaml:"metadata,omitempty" xml:"-"`
Scripts []*Script `json:"scripts,omitempty" yaml:"scripts,omitempty" xml:"scripts,omitempty"`
Sequence uint `json:"sequence,omitempty" yaml:"sequence,omitempty" xml:"sequence,omitempty"`
}
// SQLName returns the schema name in lowercase
func (d *Schema) SQLName() string {
return strings.ToLower(d.Name)
}
type Table struct {
Name string `json:"name" yaml:"name" xml:"name"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
Schema string `json:"schema" yaml:"schema" xml:"schema"`
Columns map[string]*Column `json:"columns" yaml:"columns" xml:"-"`
Constraints map[string]*Constraint `json:"constraints" yaml:"constraints" xml:"-"`
@@ -36,7 +53,13 @@ type Table struct {
Relationships map[string]*Relationship `json:"relationships,omitempty" yaml:"relationships,omitempty" xml:"-"`
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
Tablespace string `json:"tablespace,omitempty" yaml:"tablespace,omitempty" xml:"tablespace,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty" yaml:"metadata,omitempty" xml:"-"`
Metadata map[string]any `json:"metadata,omitempty" yaml:"metadata,omitempty" xml:"-"`
Sequence uint `json:"sequence,omitempty" yaml:"sequence,omitempty" xml:"sequence,omitempty"`
}
// SQLName returns the table name in lowercase
func (d *Table) SQLName() string {
return strings.ToLower(d.Name)
}
func (m Table) GetPrimaryKey() *Column {
@@ -61,32 +84,46 @@ func (m Table) GetForeignKeys() []*Constraint {
// Column represents a table column
type Column struct {
Name string `json:"name" yaml:"name" xml:"name"`
Table string `json:"table" yaml:"table" xml:"table"`
Schema string `json:"schema" yaml:"schema" xml:"schema"`
Type string `json:"type" yaml:"type" xml:"type"`
Length int `json:"length,omitempty" yaml:"length,omitempty" xml:"length,omitempty"`
Precision int `json:"precision,omitempty" yaml:"precision,omitempty" xml:"precision,omitempty"`
Scale int `json:"scale,omitempty" yaml:"scale,omitempty" xml:"scale,omitempty"`
NotNull bool `json:"not_null" yaml:"not_null" xml:"not_null"`
Default interface{} `json:"default,omitempty" yaml:"default,omitempty" xml:"default,omitempty"`
AutoIncrement bool `json:"auto_increment" yaml:"auto_increment" xml:"auto_increment"`
IsPrimaryKey bool `json:"is_primary_key" yaml:"is_primary_key" xml:"is_primary_key"`
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
Collation string `json:"collation,omitempty" yaml:"collation,omitempty" xml:"collation,omitempty"`
Name string `json:"name" yaml:"name" xml:"name"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
Table string `json:"table" yaml:"table" xml:"table"`
Schema string `json:"schema" yaml:"schema" xml:"schema"`
Type string `json:"type" yaml:"type" xml:"type"`
Length int `json:"length,omitempty" yaml:"length,omitempty" xml:"length,omitempty"`
Precision int `json:"precision,omitempty" yaml:"precision,omitempty" xml:"precision,omitempty"`
Scale int `json:"scale,omitempty" yaml:"scale,omitempty" xml:"scale,omitempty"`
NotNull bool `json:"not_null" yaml:"not_null" xml:"not_null"`
Default any `json:"default,omitempty" yaml:"default,omitempty" xml:"default,omitempty"`
AutoIncrement bool `json:"auto_increment" yaml:"auto_increment" xml:"auto_increment"`
IsPrimaryKey bool `json:"is_primary_key" yaml:"is_primary_key" xml:"is_primary_key"`
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
Collation string `json:"collation,omitempty" yaml:"collation,omitempty" xml:"collation,omitempty"`
Sequence uint `json:"sequence,omitempty" yaml:"sequence,omitempty" xml:"sequence,omitempty"`
}
// SQLName returns the table name in lowercase
func (d *Column) SQLName() string {
return strings.ToLower(d.Name)
}
type Index struct {
Name string `json:"name" yaml:"name" xml:"name"`
Table string `json:"table,omitempty" yaml:"table,omitempty" xml:"table,omitempty"`
Schema string `json:"schema,omitempty" yaml:"schema,omitempty" xml:"schema,omitempty"`
Columns []string `json:"columns" yaml:"columns" xml:"columns"`
Unique bool `json:"unique" yaml:"unique" xml:"unique"`
Type string `json:"type" yaml:"type" xml:"type"` // btree, hash, gin, gist, etc.
Where string `json:"where,omitempty" yaml:"where,omitempty" xml:"where,omitempty"` // partial index condition
Concurrent bool `json:"concurrent,omitempty" yaml:"concurrent,omitempty" xml:"concurrent,omitempty"`
Include []string `json:"include,omitempty" yaml:"include,omitempty" xml:"include,omitempty"` // INCLUDE columns
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
Name string `json:"name" yaml:"name" xml:"name"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
Table string `json:"table,omitempty" yaml:"table,omitempty" xml:"table,omitempty"`
Schema string `json:"schema,omitempty" yaml:"schema,omitempty" xml:"schema,omitempty"`
Columns []string `json:"columns" yaml:"columns" xml:"columns"`
Unique bool `json:"unique" yaml:"unique" xml:"unique"`
Type string `json:"type" yaml:"type" xml:"type"` // btree, hash, gin, gist, etc.
Where string `json:"where,omitempty" yaml:"where,omitempty" xml:"where,omitempty"` // partial index condition
Concurrent bool `json:"concurrent,omitempty" yaml:"concurrent,omitempty" xml:"concurrent,omitempty"`
Include []string `json:"include,omitempty" yaml:"include,omitempty" xml:"include,omitempty"` // INCLUDE columns
Comment string `json:"comment,omitempty" yaml:"comment,omitempty" xml:"comment,omitempty"`
Sequence uint `json:"sequence,omitempty" yaml:"sequence,omitempty" xml:"sequence,omitempty"`
}
// SQLName returns the Indexin lowercase
func (d *Index) SQLName() string {
return strings.ToLower(d.Name)
}
type RelationType string
@@ -109,6 +146,12 @@ type Relationship struct {
ThroughTable string `json:"through_table,omitempty" yaml:"through_table,omitempty" xml:"through_table,omitempty"` // For many-to-many
ThroughSchema string `json:"through_schema,omitempty" yaml:"through_schema,omitempty" xml:"through_schema,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
Sequence uint `json:"sequence,omitempty" yaml:"sequence,omitempty" xml:"sequence,omitempty"`
}
// SQLName returns the Relationship lowercase
func (d *Relationship) SQLName() string {
return strings.ToLower(d.Name)
}
type Constraint struct {
@@ -125,6 +168,11 @@ type Constraint struct {
OnUpdate string `json:"on_update" yaml:"on_update" xml:"on_update"`
Deferrable bool `json:"deferrable,omitempty" yaml:"deferrable,omitempty" xml:"deferrable,omitempty"`
InitiallyDeferred bool `json:"initially_deferred,omitempty" yaml:"initially_deferred,omitempty" xml:"initially_deferred,omitempty"`
Sequence uint `json:"sequence,omitempty" yaml:"sequence,omitempty" xml:"sequence,omitempty"`
}
func (d *Constraint) SQLName() string {
return strings.ToLower(d.Name)
}
type ConstraintType string
@@ -146,4 +194,88 @@ type Script struct {
Schema string `json:"schema,omitempty" yaml:"schema,omitempty" xml:"schema,omitempty"`
Version string `json:"version,omitempty" yaml:"version,omitempty" xml:"version,omitempty"`
Priority int `json:"priority,omitempty" yaml:"priority,omitempty" xml:"priority,omitempty"`
Sequence uint `json:"sequence,omitempty" yaml:"sequence,omitempty" xml:"sequence,omitempty"`
}
func (d *Script) SQLName() string {
return strings.ToLower(d.Name)
}
// Initialize functions
// InitDatabase initializes a new Database with empty slices
func InitDatabase(name string) *Database {
return &Database{
Name: name,
Schemas: make([]*Schema, 0),
}
}
// InitSchema initializes a new Schema with empty slices and maps
func InitSchema(name string) *Schema {
return &Schema{
Name: name,
Tables: make([]*Table, 0),
Permissions: make(map[string]string),
Metadata: make(map[string]any),
Scripts: make([]*Script, 0),
}
}
// InitTable initializes a new Table with empty maps
func InitTable(name, schema string) *Table {
return &Table{
Name: name,
Schema: schema,
Columns: make(map[string]*Column),
Constraints: make(map[string]*Constraint),
Indexes: make(map[string]*Index),
Relationships: make(map[string]*Relationship),
Metadata: make(map[string]any),
}
}
// InitColumn initializes a new Column
func InitColumn(name, table, schema string) *Column {
return &Column{
Name: name,
Table: table,
Schema: schema,
}
}
// InitIndex initializes a new Index with empty slices
func InitIndex(name string) *Index {
return &Index{
Name: name,
Columns: make([]string, 0),
Include: make([]string, 0),
}
}
// InitRelationship initializes a new Relationship with empty maps
func InitRelationship(name string, relType RelationType) *Relationship {
return &Relationship{
Name: name,
Type: relType,
Properties: make(map[string]string),
}
}
// InitConstraint initializes a new Constraint with empty slices
func InitConstraint(name string, constraintType ConstraintType) *Constraint {
return &Constraint{
Name: name,
Type: constraintType,
Columns: make([]string, 0),
ReferencedColumns: make([]string, 0),
}
}
// InitScript initializes a new Script with empty slices
func InitScript(name string) *Script {
return &Script{
Name: name,
RunAfter: make([]string, 0),
}
}

99
pkg/models/summaryview.go Normal file
View File

@@ -0,0 +1,99 @@
package models
// =============================================================================
// Summary/Compact Views - Lightweight views with essential fields
// =============================================================================
// DatabaseSummary provides a compact overview of a database
type DatabaseSummary struct {
Name string `json:"name" yaml:"name" xml:"name"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
DatabaseType DatabaseType `json:"database_type,omitempty" yaml:"database_type,omitempty" xml:"database_type,omitempty"`
DatabaseVersion string `json:"database_version,omitempty" yaml:"database_version,omitempty" xml:"database_version,omitempty"`
SchemaCount int `json:"schema_count" yaml:"schema_count" xml:"schema_count"`
TotalTables int `json:"total_tables" yaml:"total_tables" xml:"total_tables"`
TotalColumns int `json:"total_columns" yaml:"total_columns" xml:"total_columns"`
}
// ToSummary converts a Database to a DatabaseSummary
func (d *Database) ToSummary() *DatabaseSummary {
summary := &DatabaseSummary{
Name: d.Name,
Description: d.Description,
DatabaseType: d.DatabaseType,
DatabaseVersion: d.DatabaseVersion,
SchemaCount: len(d.Schemas),
}
// Count total tables and columns
for _, schema := range d.Schemas {
summary.TotalTables += len(schema.Tables)
for _, table := range schema.Tables {
summary.TotalColumns += len(table.Columns)
}
}
return summary
}
// SchemaSummary provides a compact overview of a schema
type SchemaSummary struct {
Name string `json:"name" yaml:"name" xml:"name"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
Owner string `json:"owner" yaml:"owner" xml:"owner"`
TableCount int `json:"table_count" yaml:"table_count" xml:"table_count"`
ScriptCount int `json:"script_count" yaml:"script_count" xml:"script_count"`
TotalColumns int `json:"total_columns" yaml:"total_columns" xml:"total_columns"`
TotalConstraints int `json:"total_constraints" yaml:"total_constraints" xml:"total_constraints"`
}
// ToSummary converts a Schema to a SchemaSummary
func (s *Schema) ToSummary() *SchemaSummary {
summary := &SchemaSummary{
Name: s.Name,
Description: s.Description,
Owner: s.Owner,
TableCount: len(s.Tables),
ScriptCount: len(s.Scripts),
}
// Count columns and constraints
for _, table := range s.Tables {
summary.TotalColumns += len(table.Columns)
summary.TotalConstraints += len(table.Constraints)
}
return summary
}
// TableSummary provides a compact overview of a table
type TableSummary struct {
Name string `json:"name" yaml:"name" xml:"name"`
Schema string `json:"schema" yaml:"schema" xml:"schema"`
Description string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,omitempty"`
ColumnCount int `json:"column_count" yaml:"column_count" xml:"column_count"`
ConstraintCount int `json:"constraint_count" yaml:"constraint_count" xml:"constraint_count"`
IndexCount int `json:"index_count" yaml:"index_count" xml:"index_count"`
RelationshipCount int `json:"relationship_count" yaml:"relationship_count" xml:"relationship_count"`
HasPrimaryKey bool `json:"has_primary_key" yaml:"has_primary_key" xml:"has_primary_key"`
ForeignKeyCount int `json:"foreign_key_count" yaml:"foreign_key_count" xml:"foreign_key_count"`
}
// ToSummary converts a Table to a TableSummary
func (t *Table) ToSummary() *TableSummary {
summary := &TableSummary{
Name: t.Name,
Schema: t.Schema,
Description: t.Description,
ColumnCount: len(t.Columns),
ConstraintCount: len(t.Constraints),
IndexCount: len(t.Indexes),
RelationshipCount: len(t.Relationships),
HasPrimaryKey: t.GetPrimaryKey() != nil,
}
// Count foreign keys
summary.ForeignKeyCount = len(t.GetForeignKeys())
return summary
}