Files
database_render/internal/repository/data_repository.go
2025-08-06 11:12:16 +08:00

210 lines
5.8 KiB
Go

package repository
import (
"fmt"
"log/slog"
"github.com/rogeecn/database_render/internal/config"
"github.com/rogeecn/database_render/internal/database"
"github.com/rogeecn/database_render/internal/model"
)
// DataRepository handles data access operations
type DataRepository struct {
db *database.ConnectionManager
config *config.Config
logger *slog.Logger
}
// NewDataRepository creates a new data repository
func NewDataRepository(db *database.ConnectionManager, cfg *config.Config) *DataRepository {
return &DataRepository{
db: db,
config: cfg,
logger: slog.With("component", "repository"),
}
}
// GetTables returns all configured tables
func (r *DataRepository) GetTables() ([]model.TableInfo, error) {
var tables []model.TableInfo
for name, tableConfig := range r.config.Tables {
// Get row count for each table
rowCount, err := r.db.GetTableRowCount(name)
if err != nil {
r.logger.Error("failed to get row count for table", "table", name, "error", err)
rowCount = 0
}
// Use table alias as description if not provided
description := tableConfig.Alias
if desc, ok := tableConfig.Options["description"]; ok {
if descStr, ok := desc.(string); ok {
description = descStr
}
}
tables = append(tables, model.TableInfo{
Name: name,
Alias: tableConfig.Alias,
Description: description,
RowCount: rowCount,
})
}
return tables, nil
}
// GetTableConfig returns the configuration for a specific table
func (r *DataRepository) GetTableConfig(tableName string) (*model.TableConfig, error) {
tableConfig, exists := r.config.Tables[tableName]
if !exists {
return nil, fmt.Errorf("table %s not found in configuration", tableName)
}
// Convert internal config to model config
config := &model.TableConfig{
Name: tableName,
Alias: tableConfig.Alias,
PageSize: tableConfig.PageSize,
Columns: []model.ColumnConfig{},
Filters: []model.FilterConfig{},
Options: tableConfig.Options,
}
// Convert field configurations
for fieldName, fieldConfig := range tableConfig.Fields {
column := model.ColumnConfig{
Name: fieldName,
Alias: fieldName,
RenderType: fieldConfig.Type,
Sortable: true, // Default to true
Searchable: fieldConfig.Searchable,
ShowInList: !fieldConfig.Hidden,
IsPrimaryContent: fieldConfig.Markdown,
MaxLength: fieldConfig.MaxLength,
Width: fieldConfig.Size,
Format: fieldConfig.Format,
Values: make(map[string]model.TagValue),
Options: fieldConfig.Options,
}
// Handle tag values if colors are provided
if len(fieldConfig.Colors) > 0 {
for key, color := range fieldConfig.Colors {
label := key
column.Values[key] = model.TagValue{
Label: label,
Color: color,
}
}
}
config.Columns = append(config.Columns, column)
}
return config, nil
}
// GetTableData retrieves paginated data from a table
func (r *DataRepository) GetTableData(tableName string, page, pageSize int, search string, sortField string, sortOrder string) ([]map[string]interface{}, int64, error) {
// Validate table exists in config
_, exists := r.config.Tables[tableName]
if !exists {
return nil, 0, fmt.Errorf("table %s not found in configuration", tableName)
}
// Get data from database
data, total, err := r.db.GetTableData(tableName, page, pageSize, search, sortField, sortOrder)
if err != nil {
r.logger.Error("failed to get table data",
"table", tableName,
"page", page,
"error", err)
return nil, 0, fmt.Errorf("failed to get table data: %w", err)
}
r.logger.Debug("retrieved table data",
"table", tableName,
"page", page,
"pageSize", pageSize,
"total", total,
"records", len(data))
return data, total, nil
}
// GetTableDataByID retrieves a single record by ID
func (r *DataRepository) GetTableDataByID(tableName string, id interface{}) (map[string]interface{}, error) {
// Validate table exists in config
_, exists := r.config.Tables[tableName]
if !exists {
return nil, fmt.Errorf("table %s not found in configuration", tableName)
}
// Get data from database
data, err := r.db.GetTableDataByID(tableName, id)
if err != nil {
r.logger.Error("failed to get table data by ID",
"table", tableName,
"id", id,
"error", err)
return nil, fmt.Errorf("failed to get table data by ID: %w", err)
}
r.logger.Debug("retrieved single record",
"table", tableName,
"id", id)
return data, nil
}
// GetTableColumns returns column information for a table
func (r *DataRepository) GetTableColumns(tableName string) ([]database.ColumnInfo, error) {
// Validate table exists in config
_, exists := r.config.Tables[tableName]
if !exists {
return nil, fmt.Errorf("table %s not found in configuration", tableName)
}
// Get column information from database
columns, err := r.db.GetTableColumns(tableName)
if err != nil {
r.logger.Error("failed to get table columns",
"table", tableName,
"error", err)
return nil, fmt.Errorf("failed to get table columns: %w", err)
}
return columns, nil
}
// ValidateTableConfig validates if the configured tables exist in the database
func (r *DataRepository) ValidateTableConfig() error {
// Get all table names from database
dbTables, err := r.db.GetTableNames()
if err != nil {
return fmt.Errorf("failed to get table names from database: %w", err)
}
// Create a map for quick lookup
dbTableMap := make(map[string]bool)
for _, table := range dbTables {
dbTableMap[table] = true
}
// Check if all configured tables exist
for tableName := range r.config.Tables {
if !dbTableMap[tableName] {
return fmt.Errorf("table %s not found in database", tableName)
}
}
r.logger.Info("table configuration validation completed",
"configured_tables", len(r.config.Tables),
"database_tables", len(dbTables))
return nil
}