# Tables Service Kind

## Overview

Tables are entity-specific services responsible for database-to-domain model mapping and data transformation. They handle the conversion between database representations (with nullable SQL types) and domain entities, provide metadata about database schema, and manage field-level data transformations.

## Architecture

### Core Components

**Entity-Specific Tables** (`src/srv/tables/`)
- Each domain model has its own dedicated table service (e.g., `GardenTable`, `UserTable`)
- All tables follow the same interface pattern and method conventions
- No base library - tables implement focused data mapping logic

**Key Data Structures**
- **Entity Structs**: Domain model entities with Go native types
- **ESO Structs**: Entity Storage Objects with SQL-compatible nullable types
- **Mapping Methods**: Bidirectional conversion between ESOs and entities

### Naming Convention

Tables follow a consistent naming pattern:
- **Table Services**: `{Entity}Table` (e.g., `GardenTable`)
- **Storage Objects**: `{Entity}Eso` (e.g., `GardenEso`)
- ESO = Entity Storage Object (database-compatible representation)

## Standard Methods

Every table service implements these standard methods:

### Entity Conversion
```go
EsoToEntity(eso) *Entity
```
- Convert ESO (database representation) to domain entity
- Handle NULL value conversion to Go zero values
- Transform SQL types to native Go types

### Database Scanning Support
```go
EsoToPointers(eso) []interface{}
```
- Generate pointers for SQL row scanning
- Return slice of field pointers for `rows.Scan()`
- Enable efficient database result processing

### Entity-to-Values Conversion
```go
EntityToValues(entity) []interface{}
```
- Convert domain entity to database values
- Transform native Go types to SQL-compatible values
- Support database insertion and update operations

### Metadata Methods
```go
TableName() string               // Database table name
Columns() []string              // Database column names
Fields() []string               // Go struct field names
ColumnsWithoutId() []string     // Columns excluding ID field
```

## Usage Examples

### Database Result Processing
```go
// In Fetcher services
eso := &tables.GardenEso{}
row := db.QueryRow(query, args...)
err := row.Scan(gardenTable.EsoToPointers(eso)...)

// Convert to domain entity
entity := gardenTable.EsoToEntity(eso)
```

### Database Operations
```go
// In Handler services
values := gardenTable.EntityToValues(entity)
columns := gardenTable.Columns()
tableName := gardenTable.TableName()

// Use for INSERT/UPDATE operations
```

### Field Mapping
```go
// Get metadata for query building
columns := gardenTable.Columns()       // ["id", "created_at", "updated_at", "name", "picture"]
fields := gardenTable.Fields()         // ["Id", "CreatedAt", "UpdatedAt", "Name", "Picture"]
table := gardenTable.TableName()       // "gardens"
```

## ESO (Entity Storage Object) Pattern

ESOs represent database-compatible entity structures:

### SQL-Compatible Types
```go
type GardenEso struct {
    Id        string        // Direct mapping for required fields
    CreatedAt sql.NullTime  // Nullable database fields
    UpdatedAt sql.NullTime  // Handle NULL values properly
    Name      string        // Required business fields
    Picture   string        // Optional but non-null fields
}
```

### NULL Handling
- **sql.NullTime**: For optional timestamp fields
- **sql.NullString**: For optional text fields
- **sql.NullInt64**: For optional integer fields
- **sql.NullBool**: For optional boolean fields

## Entity Conversion Logic

### ESO to Entity
```go
func (this *GardenTable) EsoToEntity(eso *GardenEso) *mdl.Garden {
    entity := &mdl.Garden{}
    entity.Id = eso.Id
    entity.CreatedAt = eso.CreatedAt.Time    // Extract Time from sql.NullTime
    entity.UpdatedAt = eso.UpdatedAt.Time    // Handle null as zero value
    entity.Name = eso.Name
    entity.Picture = eso.Picture
    return entity
}
```

### Entity to Values
```go
func (this *GardenTable) EntityToValues(entity *mdl.Garden) []interface{} {
    var values []interface{}
    values = append(values,
        entity.Id,
        entity.CreatedAt,    // Go time.Time converts to SQL timestamp
        entity.UpdatedAt,
        entity.Name,
        entity.Picture,
    )
    return values
}
```

## Database Scanning Support

Tables provide efficient scanning support for SQL queries:

### Pointer Generation
```go
func (this *GardenTable) EsoToPointers(eso *GardenEso) []interface{} {
    var values []interface{}
    values = append(values,
        &eso.Id,        // Pointer to string field
        &eso.CreatedAt, // Pointer to sql.NullTime
        &eso.UpdatedAt, // Pointer to sql.NullTime
        &eso.Name,      // Pointer to string field
        &eso.Picture,   // Pointer to string field
    )
    return values
}
```

### Usage in Fetchers
```go
// Efficient scanning with generated pointers
fields := gardenTable.EsoToPointers(eso)
err := rows.Scan(fields...)
```

## Schema Metadata

Tables provide comprehensive database schema metadata:

### Column Management
```go
// Full column list
columns := gardenTable.Columns()
// ["id", "created_at", "updated_at", "name", "picture"]

// Columns without ID (for INSERT operations)
insertColumns := gardenTable.ColumnsWithoutId()
// ["created_at", "updated_at", "name", "picture"]
```

### Field Mapping
```go
// Go struct field names
fields := gardenTable.Fields()
// ["Id", "CreatedAt", "UpdatedAt", "Name", "Picture"]
```

## Integration with Framework

### With Fetchers
- Provide ESO scanning support
- Convert database results to entities
- Supply schema metadata for query building

### With Handlers
- Convert entities to database values
- Provide column lists for SQL operations
- Supply table names for query construction

### With Serializers
- Field name mapping for JSON output
- Entity value extraction for serialization

## Type Safety

Tables maintain type safety throughout the conversion process:
- **Compile-time checking**: All conversions use statically typed methods
- **NULL safety**: Proper handling of nullable database fields
- **Type conversion**: Safe conversion between SQL and Go types
- **Field ordering**: Consistent field ordering across all operations

## Performance Considerations

- **Direct field access**: No reflection-based mapping for better performance
- **Efficient scanning**: Pre-allocated pointer slices for database scanning
- **Memory efficiency**: Reusable ESO structures
- **Minimal allocations**: Optimized conversion methods