156 lines
7.5 KiB
SQL
156 lines
7.5 KiB
SQL
CREATE TABLE users (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
email VARCHAR(320) NOT NULL,
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
display_name VARCHAR(120) NOT NULL,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
|
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
|
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_users_email (email),
|
|
CONSTRAINT chk_users_status CHECK (status IN ('active', 'disabled'))
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE providers (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
slug VARCHAR(80) NOT NULL,
|
|
name VARCHAR(120) NOT NULL,
|
|
base_url VARCHAR(2048) NOT NULL,
|
|
auth_type VARCHAR(16) NOT NULL DEFAULT 'bearer',
|
|
api_key_enc JSON NULL,
|
|
enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
|
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
|
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_providers_slug (slug),
|
|
CONSTRAINT chk_providers_auth CHECK (
|
|
(auth_type = 'none' AND api_key_enc IS NULL) OR
|
|
(auth_type = 'bearer' AND api_key_enc IS NOT NULL)
|
|
)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE provider_models (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
provider_id BIGINT UNSIGNED NOT NULL,
|
|
name VARCHAR(120) NOT NULL,
|
|
model_id VARCHAR(191) NOT NULL,
|
|
api_type VARCHAR(32) NOT NULL,
|
|
kind VARCHAR(16) NOT NULL,
|
|
extra_body JSON NOT NULL,
|
|
timeout_ms INT UNSIGNED NOT NULL,
|
|
weight INT UNSIGNED NOT NULL DEFAULT 100,
|
|
enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
|
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
|
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_provider_models_binding (provider_id, model_id, api_type),
|
|
KEY idx_provider_models_route (kind, api_type, enabled),
|
|
CONSTRAINT fk_provider_models_provider FOREIGN KEY (provider_id) REFERENCES providers (id) ON DELETE CASCADE,
|
|
CONSTRAINT chk_provider_models_api_type CHECK (api_type IN ('chat', 'images', 'images_edits', 'gemini')),
|
|
CONSTRAINT chk_provider_models_kind CHECK (kind IN ('text', 'image')),
|
|
CONSTRAINT chk_provider_models_timeout CHECK (timeout_ms > 0),
|
|
CONSTRAINT chk_provider_models_weight CHECK (weight > 0)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE prompt_templates (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
template_key VARCHAR(120) NOT NULL,
|
|
kind VARCHAR(16) NOT NULL,
|
|
api_type VARCHAR(32) NOT NULL,
|
|
name VARCHAR(120) NOT NULL,
|
|
version INT UNSIGNED NOT NULL,
|
|
template_text TEXT NOT NULL,
|
|
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
|
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_prompt_templates_key (template_key),
|
|
KEY idx_prompt_templates_selection (kind, api_type, enabled, version),
|
|
CONSTRAINT chk_prompt_templates_kind CHECK (kind IN ('text', 'image')),
|
|
CONSTRAINT chk_prompt_templates_api_type CHECK (api_type IN ('chat', 'images', 'images_edits', 'gemini')),
|
|
CONSTRAINT chk_prompt_templates_version CHECK (version > 0)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE generations (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
user_id BIGINT UNSIGNED NOT NULL,
|
|
provider_model_id BIGINT UNSIGNED NULL,
|
|
kind VARCHAR(16) NOT NULL,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'pending',
|
|
idempotency_key VARCHAR(128) NOT NULL,
|
|
user_prompt TEXT NOT NULL,
|
|
rendered_prompt TEXT NOT NULL,
|
|
attempts JSON NOT NULL,
|
|
attempt_count INT UNSIGNED NOT NULL DEFAULT 0,
|
|
error_code VARCHAR(64) NULL,
|
|
error_message VARCHAR(1024) NULL,
|
|
lease_owner VARCHAR(128) NULL,
|
|
lease_token CHAR(36) NULL,
|
|
lease_until DATETIME(6) NULL,
|
|
started_at DATETIME(6) NULL,
|
|
completed_at DATETIME(6) NULL,
|
|
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
|
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_generations_user_idempotency (user_id, idempotency_key),
|
|
KEY idx_generations_queue (status, lease_until, created_at),
|
|
KEY idx_generations_user_history (user_id, created_at, id),
|
|
KEY idx_generations_provider_model (provider_model_id),
|
|
CONSTRAINT fk_generations_user FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE RESTRICT,
|
|
CONSTRAINT fk_generations_provider_model FOREIGN KEY (provider_model_id) REFERENCES provider_models (id) ON DELETE SET NULL,
|
|
CONSTRAINT chk_generations_kind CHECK (kind IN ('text', 'image')),
|
|
CONSTRAINT chk_generations_status CHECK (status IN ('pending', 'running', 'succeeded', 'failed')),
|
|
CONSTRAINT chk_generations_attempts CHECK (
|
|
JSON_TYPE(attempts) = 'ARRAY' AND attempt_count = JSON_LENGTH(attempts)
|
|
),
|
|
CONSTRAINT chk_generations_lease CHECK (
|
|
(status = 'running' AND lease_owner IS NOT NULL AND lease_token IS NOT NULL AND lease_until IS NOT NULL) OR
|
|
(status <> 'running')
|
|
),
|
|
CONSTRAINT chk_generations_error CHECK (
|
|
(status = 'failed' AND error_code IS NOT NULL AND error_message IS NOT NULL) OR
|
|
(status <> 'failed')
|
|
)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE generation_inputs (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
generation_id BIGINT UNSIGNED NOT NULL,
|
|
position INT UNSIGNED NOT NULL,
|
|
role VARCHAR(16) NOT NULL,
|
|
original_name VARCHAR(255) NOT NULL,
|
|
mime_type VARCHAR(120) NOT NULL,
|
|
storage_key VARCHAR(512) NOT NULL,
|
|
size_bytes BIGINT UNSIGNED NOT NULL,
|
|
width INT UNSIGNED NULL,
|
|
height INT UNSIGNED NULL,
|
|
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_generation_inputs_position (generation_id, position),
|
|
KEY idx_generation_inputs_generation (generation_id),
|
|
CONSTRAINT fk_generation_inputs_generation FOREIGN KEY (generation_id) REFERENCES generations (id) ON DELETE CASCADE,
|
|
CONSTRAINT chk_generation_inputs_role CHECK (role IN ('primary', 'reference'))
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE generation_outputs (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
generation_id BIGINT UNSIGNED NOT NULL,
|
|
kind VARCHAR(16) NOT NULL,
|
|
text_content MEDIUMTEXT NULL,
|
|
storage_key VARCHAR(512) NULL,
|
|
thumbnail_storage_key VARCHAR(512) NULL,
|
|
mime_type VARCHAR(120) NULL,
|
|
size_bytes BIGINT UNSIGNED NULL,
|
|
width INT UNSIGNED NULL,
|
|
height INT UNSIGNED NULL,
|
|
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
|
PRIMARY KEY (id),
|
|
KEY idx_generation_outputs_generation (generation_id, id),
|
|
CONSTRAINT fk_generation_outputs_generation FOREIGN KEY (generation_id) REFERENCES generations (id) ON DELETE CASCADE,
|
|
CONSTRAINT chk_generation_outputs_kind CHECK (kind IN ('text', 'image')),
|
|
CONSTRAINT chk_generation_outputs_content CHECK (
|
|
(kind = 'text' AND text_content IS NOT NULL AND storage_key IS NULL AND thumbnail_storage_key IS NULL) OR
|
|
(kind = 'image' AND text_content IS NULL AND storage_key IS NOT NULL AND thumbnail_storage_key IS NOT NULL)
|
|
)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|