2026-05-18 19:46:21 +07:00
|
|
|
CREATE TABLE IF NOT EXISTS files (
|
2026-05-18 06:51:06 +07:00
|
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
|
public_id VARCHAR(21) UNIQUE NOT NULL,
|
|
|
|
|
telegram_file_id VARCHAR NOT NULL,
|
|
|
|
|
telegram_file_unique_id VARCHAR NOT NULL,
|
|
|
|
|
storage_chat_id BIGINT NOT NULL,
|
|
|
|
|
storage_message_id BIGINT NOT NULL,
|
|
|
|
|
file_name VARCHAR NOT NULL,
|
|
|
|
|
mime_type VARCHAR NOT NULL,
|
|
|
|
|
size_bytes BIGINT NOT NULL,
|
|
|
|
|
file_type VARCHAR NOT NULL,
|
|
|
|
|
uploader_id BIGINT NOT NULL,
|
2026-05-18 19:46:21 +07:00
|
|
|
file_hash VARCHAR,
|
2026-05-22 00:51:49 +07:00
|
|
|
archive_telegram_file_id VARCHAR,
|
|
|
|
|
archive_storage_message_id BIGINT,
|
|
|
|
|
archive_file_name VARCHAR,
|
|
|
|
|
archive_entry_name VARCHAR,
|
|
|
|
|
archive_mime_type VARCHAR,
|
|
|
|
|
archive_size_bytes BIGINT,
|
2026-05-18 06:51:06 +07:00
|
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
);
|
|
|
|
|
|
2026-05-18 19:46:21 +07:00
|
|
|
CREATE INDEX IF NOT EXISTS idx_files_public_id ON files(public_id);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_files_telegram_file_id ON files(telegram_file_id);
|
2026-05-21 22:55:42 +07:00
|
|
|
CREATE INDEX IF NOT EXISTS idx_files_file_hash ON files(file_hash);
|
2026-05-22 00:51:49 +07:00
|
|
|
CREATE INDEX IF NOT EXISTS idx_files_archive_telegram_file_id ON files(archive_telegram_file_id);
|
2026-05-18 19:46:21 +07:00
|
|
|
CREATE INDEX IF NOT EXISTS idx_files_uploader_id ON files(uploader_id);
|
2026-07-06 13:59:03 +07:00
|
|
|
CREATE INDEX IF NOT EXISTS idx_files_created_at ON files(created_at DESC);
|
|
|
|
|
|
|
|
|
|
-- S3-compatible buckets
|
|
|
|
|
CREATE TABLE IF NOT EXISTS buckets (
|
|
|
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
|
name VARCHAR(63) UNIQUE NOT NULL,
|
|
|
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
-- Extend files table for S3
|
|
|
|
|
ALTER TABLE files ADD COLUMN IF NOT EXISTS bucket_id UUID REFERENCES buckets(id);
|
|
|
|
|
ALTER TABLE files ADD COLUMN IF NOT EXISTS s3_key TEXT;
|
|
|
|
|
ALTER TABLE files ADD COLUMN IF NOT EXISTS storage_backend VARCHAR DEFAULT 'telegram';
|
|
|
|
|
ALTER TABLE files ADD COLUMN IF NOT EXISTS is_deleted BOOLEAN DEFAULT false;
|
|
|
|
|
ALTER TABLE files ADD COLUMN IF NOT EXISTS multipart_upload_id TEXT;
|
|
|
|
|
|
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_files_bucket_key ON files(bucket_id, s3_key) WHERE is_deleted = false;
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_files_bucket_prefix ON files(bucket_id, s3_key text_pattern_ops);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_files_s3_key ON files(s3_key);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_files_bucket_id ON files(bucket_id);
|
|
|
|
|
|
|
|
|
|
-- Multipart upload tracking
|
|
|
|
|
CREATE TABLE IF NOT EXISTS multipart_uploads (
|
|
|
|
|
upload_id VARCHAR PRIMARY KEY,
|
|
|
|
|
bucket_id UUID NOT NULL REFERENCES buckets(id),
|
|
|
|
|
s3_key TEXT NOT NULL,
|
|
|
|
|
initiated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
status VARCHAR DEFAULT 'in_progress',
|
|
|
|
|
initiated_by TEXT
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS multipart_parts (
|
|
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
|
|
upload_id VARCHAR NOT NULL REFERENCES multipart_uploads(upload_id) ON DELETE CASCADE,
|
|
|
|
|
part_number INT NOT NULL,
|
|
|
|
|
telegram_file_id VARCHAR NOT NULL,
|
|
|
|
|
telegram_file_unique_id VARCHAR NOT NULL,
|
|
|
|
|
storage_message_id BIGINT NOT NULL,
|
|
|
|
|
size_bytes BIGINT NOT NULL,
|
|
|
|
|
etag VARCHAR NOT NULL,
|
|
|
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
UNIQUE(upload_id, part_number)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_multipart_parts_upload ON multipart_parts(upload_id, part_number);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_multipart_uploads_status ON multipart_uploads(status);
|