203 lines
10 KiB
Go
203 lines
10 KiB
Go
package models
|
|
|
|
import "fmt"
|
|
|
|
// Flat/Denormalized Views
|
|
//
|
|
// This file provides flattened data structures with fully qualified names
|
|
// for easier querying and analysis of database schemas without navigating
|
|
// nested hierarchies.
|
|
|
|
// FlatColumn represents a column with full database context in a single structure.
|
|
// It includes fully qualified names for easy identification and querying.
|
|
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 for denormalized access to all columns.
|
|
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 database context and aggregated counts.
|
|
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 for denormalized access to all tables.
|
|
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 database context and resolved references.
|
|
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 for denormalized access to all constraints.
|
|
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 database context and fully qualified table names.
|
|
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 for denormalized access to all relationships.
|
|
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
|
|
}
|