251 lines
7.1 KiB
Markdown
251 lines
7.1 KiB
Markdown
# Package database
|
|
|
|
## Overview
|
|
|
|
Package database provides the data access layer for the query orchestration platform. It manages PostgreSQL database connections, schema migrations, and generated query functions using SQLC. The package implements a repository pattern with type-safe database operations and comprehensive transaction support.
|
|
|
|
## Architecture
|
|
|
|
### Core Components
|
|
|
|
#### Database Schema
|
|
The database schema supports document processing and query orchestration with the following key entities:
|
|
- **Clients**: Customer configurations with associated document sets
|
|
- **Documents**: Uploaded files with processing state tracking
|
|
- **Queries**: Data extraction and processing definitions with versioning
|
|
- **Collectors**: Query collection specifications per client
|
|
- **Results**: Processed query outputs linked to documents
|
|
- **Text Extractions**: OCR results from document processing
|
|
|
|
#### Migration System
|
|
- Uses `golang-migrate` for schema version management
|
|
- Migrations stored in `migrations/` directory with up/down SQL files
|
|
- Automatic migration execution on startup
|
|
- Support for extensions, tables, views, and functions
|
|
|
|
#### Query Generation
|
|
- SQLC generates type-safe Go code from SQL queries
|
|
- Query definitions in `queries/` directory
|
|
- Generated code in `repository/` subdirectory
|
|
- Automatic struct mapping and null handling
|
|
|
|
### Key Files
|
|
|
|
- **migrations.go**: Database migration management and execution
|
|
- **queries/*.sql**: SQLC query definitions for each entity
|
|
- **repository/db.go**: Database connection interface and transaction support
|
|
- **repository/*.sql.go**: Generated query functions from SQLC
|
|
- **repository/models.go**: Generated data models and type definitions
|
|
- **database.md**: Schema documentation with Mermaid diagram
|
|
- **diagram.mmd**: Visual database schema representation
|
|
|
|
## Database Schema Design
|
|
|
|
### Tables
|
|
|
|
#### Core Tables
|
|
- **clients**: Customer configurations and metadata
|
|
- **documents**: Document upload tracking and processing status
|
|
- **documentCleans**: Cleaned document content storage
|
|
- **documentTextExtractions**: OCR text extraction results
|
|
- **queries**: Query definitions with JSON configurations
|
|
- **queryVersions**: Query version history and dependency tracking
|
|
- **results**: Query execution results per document
|
|
- **collectors**: Client-specific query collections
|
|
- **collectorVersions**: Collector version history
|
|
|
|
### Views
|
|
|
|
#### Query Views
|
|
- **fullActiveQueries**: Complete active query information with dependencies
|
|
- **queryActiveVersions**: Current active version for each query
|
|
- **queryActiveDependencies**: Recursive dependency resolution
|
|
- **activeQueryNameTypeMap**: Mapping of query names to types
|
|
|
|
#### Collector Views
|
|
- **fullActiveCollectorVersions**: Active collector configurations
|
|
- **collectorActiveVersions**: Current version for each collector
|
|
- **collectorQueryDependencyTree**: Full dependency graph for collectors
|
|
|
|
#### Document Views
|
|
- **currentTextEntries**: Latest text extraction for each document
|
|
- **latestDocumentTextResults**: Most recent results per document
|
|
|
|
### Custom Functions
|
|
- **uuid_generate_v7()**: Generates time-ordered UUIDs for better indexing
|
|
- **json_matches_schema()**: Validates JSON against schema definitions
|
|
|
|
## Usage
|
|
|
|
### Database Connection
|
|
|
|
```go
|
|
// Create database configuration
|
|
dbConfig := &serviceconfig.DBConfig{
|
|
DBHost: "localhost",
|
|
DBPort: "5432",
|
|
DBName: "querydb",
|
|
DBUser: "dbuser",
|
|
DBPassword: "dbpass",
|
|
}
|
|
|
|
// Get connection pool
|
|
pool, err := dbConfig.GetDBPool(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer pool.Close()
|
|
|
|
// Create repository queries instance
|
|
queries := repository.New(pool)
|
|
```
|
|
|
|
### Transaction Management
|
|
|
|
```go
|
|
// Execute operations in a transaction
|
|
err := dbConfig.ExecuteDBTransaction(ctx, func(ctx context.Context, qtx *repository.Queries) error {
|
|
// All operations here run in a single transaction
|
|
client, err := qtx.CreateClient(ctx, repository.CreateClientParams{
|
|
ID: clientID,
|
|
Name: clientName,
|
|
})
|
|
if err != nil {
|
|
return err // Transaction will rollback
|
|
}
|
|
|
|
// Additional operations...
|
|
return nil // Transaction will commit
|
|
})
|
|
```
|
|
|
|
### Query Examples
|
|
|
|
```go
|
|
// Get a document by ID
|
|
document, err := queries.GetDocument(ctx, documentID)
|
|
|
|
// List documents for a client
|
|
documents, err := queries.ListDocumentsByClient(ctx, repository.ListDocumentsByClientParams{
|
|
ClientID: clientID,
|
|
Limit: 50,
|
|
Offset: 0,
|
|
})
|
|
|
|
// Create a query result
|
|
result, err := queries.CreateResult(ctx, repository.CreateResultParams{
|
|
TextEntryID: textEntryID,
|
|
QueryID: queryID,
|
|
Result: resultJSON,
|
|
})
|
|
```
|
|
|
|
## Migration Management
|
|
|
|
### Creating Migrations
|
|
|
|
```bash
|
|
# Create a new migration
|
|
migrate create -ext sql -dir internal/database/migrations -seq add_new_feature
|
|
|
|
# This creates:
|
|
# - 000000XX_add_new_feature.up.sql
|
|
# - 000000XX_add_new_feature.down.sql
|
|
```
|
|
|
|
### Migration Conventions
|
|
- Use sequential numbering with zero padding
|
|
- Provide complete rollback logic in down migrations
|
|
- Test both up and down migrations
|
|
- Include data migrations where necessary
|
|
|
|
### Migration Execution
|
|
Migrations run automatically on application startup via:
|
|
```go
|
|
migrator := database.NewMigrator(dbURL)
|
|
err := migrator.Up()
|
|
```
|
|
|
|
## SQLC Integration
|
|
|
|
### Query Definition Format
|
|
|
|
```sql
|
|
-- name: GetDocument :one
|
|
SELECT * FROM documents
|
|
WHERE id = $1;
|
|
|
|
-- name: ListDocumentsByClient :many
|
|
SELECT * FROM documents
|
|
WHERE clientId = $1
|
|
ORDER BY created DESC
|
|
LIMIT $2 OFFSET $3;
|
|
|
|
-- name: UpdateDocumentStatus :exec
|
|
UPDATE documents
|
|
SET status = $2, updated = CURRENT_TIMESTAMP
|
|
WHERE id = $1;
|
|
```
|
|
|
|
### Generated Code
|
|
SQLC generates:
|
|
- Type-safe query functions
|
|
- Struct definitions matching table schemas
|
|
- Null handling with sql.NullString, sql.NullTime, etc.
|
|
- Parameter validation
|
|
|
|
## Testing
|
|
|
|
### Test Database Setup
|
|
Tests use testcontainers to spin up PostgreSQL instances:
|
|
```go
|
|
container := test.NewDatabaseContainer(t)
|
|
dbConfig := container.DBConfig(t)
|
|
```
|
|
|
|
### Repository Testing
|
|
- Each repository file has corresponding test coverage
|
|
- Tests validate CRUD operations
|
|
- Transaction rollback testing
|
|
- Concurrent access validation
|
|
|
|
## Performance Considerations
|
|
|
|
### Connection Pooling
|
|
- Uses pgx connection pooling
|
|
- Configurable pool size and timeouts
|
|
- Health check pings with timeout
|
|
- Automatic connection recovery
|
|
|
|
### Query Optimization
|
|
- Views provide pre-computed joins
|
|
- Recursive CTEs for dependency resolution
|
|
- Proper use of LIMIT/OFFSET for pagination
|
|
- JSON indexing for configuration queries
|
|
|
|
## Data Types
|
|
|
|
### Custom Types
|
|
- **UUID**: Used for all primary keys
|
|
- **JSONB**: Query configurations and results
|
|
- **Timestamptz**: All timestamp fields timezone-aware
|
|
- **Text**: Unbounded string storage
|
|
- **Custom Enums**: Via CHECK constraints
|
|
|
|
### Null Handling
|
|
- Explicit NULL/NOT NULL constraints
|
|
- Go sql.Null* types for nullable fields
|
|
- Default values where appropriate
|
|
|
|
## Security
|
|
|
|
### Access Control
|
|
- Database credentials via environment variables
|
|
- Connection string sanitization
|
|
- Parameterized queries prevent SQL injection
|
|
- No dynamic SQL construction
|
|
|
|
### Data Protection
|
|
- Sensitive data fields identified
|
|
- Audit fields (created, updated) on all tables
|
|
- Logical deletion support where needed |