160 lines
4.5 KiB
MySQL
160 lines
4.5 KiB
MySQL
|
|
-- 030_files_management.sql
|
||
|
|
-- File Management (Origin Standard)
|
||
|
|
|
||
|
|
-- === FILES ===
|
||
|
|
CREATE TABLE public.files (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||
|
|
|
||
|
|
-- File Info
|
||
|
|
filename VARCHAR(255) NOT NULL,
|
||
|
|
original_filename VARCHAR(255) NOT NULL,
|
||
|
|
mime_type VARCHAR(100) NOT NULL,
|
||
|
|
file_size BIGINT NOT NULL,
|
||
|
|
|
||
|
|
-- Storage
|
||
|
|
storage_path TEXT NOT NULL,
|
||
|
|
storage_provider VARCHAR(50) NOT NULL DEFAULT 's3',
|
||
|
|
bucket_name VARCHAR(255),
|
||
|
|
|
||
|
|
-- URLs
|
||
|
|
url TEXT NOT NULL,
|
||
|
|
thumbnail_url TEXT,
|
||
|
|
|
||
|
|
-- Metadata
|
||
|
|
file_hash VARCHAR(64),
|
||
|
|
metadata JSONB,
|
||
|
|
|
||
|
|
-- Processing
|
||
|
|
is_processed BOOLEAN NOT NULL DEFAULT false,
|
||
|
|
processed_at TIMESTAMPTZ,
|
||
|
|
processing_error TEXT,
|
||
|
|
|
||
|
|
-- Security
|
||
|
|
virus_scanned BOOLEAN NOT NULL DEFAULT false,
|
||
|
|
virus_scan_result VARCHAR(50),
|
||
|
|
virus_scanned_at TIMESTAMPTZ,
|
||
|
|
|
||
|
|
-- Visibility
|
||
|
|
is_public BOOLEAN NOT NULL DEFAULT false,
|
||
|
|
|
||
|
|
-- Timestamps
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
deleted_at TIMESTAMPTZ,
|
||
|
|
|
||
|
|
CONSTRAINT chk_files_size_positive CHECK (file_size > 0)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_files_user_id ON public.files(user_id);
|
||
|
|
CREATE INDEX idx_files_mime_type ON public.files(mime_type);
|
||
|
|
CREATE INDEX idx_files_file_hash ON public.files(file_hash) WHERE file_hash IS NOT NULL;
|
||
|
|
CREATE INDEX idx_files_created_at_desc ON public.files(created_at DESC);
|
||
|
|
|
||
|
|
-- === FILE UPLOADS ===
|
||
|
|
CREATE TABLE public.file_uploads (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||
|
|
|
||
|
|
-- Upload Info
|
||
|
|
filename VARCHAR(255) NOT NULL,
|
||
|
|
file_size BIGINT NOT NULL,
|
||
|
|
mime_type VARCHAR(100) NOT NULL,
|
||
|
|
|
||
|
|
-- Progress
|
||
|
|
bytes_uploaded BIGINT NOT NULL DEFAULT 0,
|
||
|
|
chunks_uploaded INTEGER NOT NULL DEFAULT 0,
|
||
|
|
total_chunks INTEGER,
|
||
|
|
|
||
|
|
-- Status
|
||
|
|
status VARCHAR(50) NOT NULL DEFAULT 'pending',
|
||
|
|
|
||
|
|
-- Storage
|
||
|
|
storage_key TEXT,
|
||
|
|
upload_id TEXT,
|
||
|
|
|
||
|
|
-- Metadata
|
||
|
|
metadata JSONB,
|
||
|
|
|
||
|
|
-- Timestamps
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
expires_at TIMESTAMPTZ NOT NULL,
|
||
|
|
|
||
|
|
CONSTRAINT chk_file_uploads_bytes_uploaded CHECK (bytes_uploaded >= 0 AND bytes_uploaded <= file_size)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_file_uploads_user_id ON public.file_uploads(user_id);
|
||
|
|
CREATE INDEX idx_file_uploads_status ON public.file_uploads(status);
|
||
|
|
CREATE INDEX idx_file_uploads_expires_at ON public.file_uploads(expires_at);
|
||
|
|
|
||
|
|
-- === FILE METADATA ===
|
||
|
|
CREATE TABLE public.file_metadata (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
file_id UUID NOT NULL REFERENCES public.files(id) ON DELETE CASCADE,
|
||
|
|
|
||
|
|
-- Audio
|
||
|
|
title VARCHAR(255),
|
||
|
|
artist VARCHAR(255),
|
||
|
|
album VARCHAR(255),
|
||
|
|
genre VARCHAR(100),
|
||
|
|
year INTEGER,
|
||
|
|
duration INTEGER,
|
||
|
|
bitrate INTEGER,
|
||
|
|
sample_rate INTEGER,
|
||
|
|
channels INTEGER,
|
||
|
|
codec VARCHAR(50),
|
||
|
|
|
||
|
|
-- Image
|
||
|
|
width INTEGER,
|
||
|
|
height INTEGER,
|
||
|
|
format VARCHAR(50),
|
||
|
|
|
||
|
|
-- Video
|
||
|
|
video_codec VARCHAR(50),
|
||
|
|
audio_codec VARCHAR(50),
|
||
|
|
framerate DECIMAL(10,2),
|
||
|
|
|
||
|
|
-- Advanced
|
||
|
|
bpm INTEGER,
|
||
|
|
musical_key VARCHAR(10),
|
||
|
|
time_signature VARCHAR(10),
|
||
|
|
|
||
|
|
-- Raw
|
||
|
|
raw_metadata JSONB,
|
||
|
|
|
||
|
|
-- Timestamps
|
||
|
|
extracted_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
|
||
|
|
CONSTRAINT uq_file_metadata_file_id UNIQUE (file_id)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_file_metadata_genre ON public.file_metadata(genre) WHERE genre IS NOT NULL;
|
||
|
|
CREATE INDEX idx_file_metadata_duration ON public.file_metadata(duration) WHERE duration IS NOT NULL;
|
||
|
|
|
||
|
|
-- === FILE CONVERSIONS ===
|
||
|
|
CREATE TABLE public.file_conversions (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
source_file_id UUID NOT NULL REFERENCES public.files(id) ON DELETE CASCADE,
|
||
|
|
converted_file_id UUID REFERENCES public.files(id) ON DELETE SET NULL,
|
||
|
|
|
||
|
|
-- Conversion
|
||
|
|
target_format VARCHAR(50) NOT NULL,
|
||
|
|
target_quality VARCHAR(50),
|
||
|
|
|
||
|
|
-- Status
|
||
|
|
status VARCHAR(50) NOT NULL DEFAULT 'pending',
|
||
|
|
progress INTEGER NOT NULL DEFAULT 0,
|
||
|
|
|
||
|
|
-- Error
|
||
|
|
error_message TEXT,
|
||
|
|
|
||
|
|
-- Timestamps
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
completed_at TIMESTAMPTZ
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_file_conversions_source_file_id ON public.file_conversions(source_file_id);
|
||
|
|
CREATE INDEX idx_file_conversions_status ON public.file_conversions(status);
|