update
This commit is contained in:
225
api/Blog.api
225
api/Blog.api
@@ -2,227 +2,38 @@ syntax = "v1"
|
|||||||
|
|
||||||
info (
|
info (
|
||||||
title: "Blog API"
|
title: "Blog API"
|
||||||
desc: "Blog service API with file upload/download and CRUD operations"
|
desc: "API for blog application with file operations"
|
||||||
author: "cialloo"
|
author: "user"
|
||||||
date: "2025-10-22"
|
date: "2025-10-24"
|
||||||
version: "v1"
|
version: "v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ============= File Upload/Download Types =============
|
type UploadReq {
|
||||||
type (
|
FileName string `json:"fileName"`
|
||||||
// Request for generating presigned upload URL
|
|
||||||
GenerateUploadUrlReq {
|
|
||||||
FileName string `json:"file_name"` // Original file name
|
|
||||||
FileSize int64 `json:"file_size"` // File size in bytes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateUploadUrlResp {
|
type UploadResp {
|
||||||
FileId int64 `json:"file_id"` // Generated file ID
|
PresignedUrl string `json:"presignedUrl"`
|
||||||
PresignedUrl string `json:"presigned_url"` // S3 presigned upload URL
|
|
||||||
FileKey string `json:"file_key"` // S3 file key
|
|
||||||
ExpiresIn int `json:"expires_in"` // URL expiration time in seconds
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request for generating presigned download URL
|
type DownloadReq {
|
||||||
GenerateDownloadUrlReq {
|
FileKey string `json:"fileKey"`
|
||||||
FileId int64 `path:"file_id"` // File ID to download
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateDownloadUrlResp {
|
type DownloadResp {
|
||||||
FileName string `json:"file_name"` // Original file name
|
PresignedUrl string `json:"presignedUrl"`
|
||||||
PresignedUrl string `json:"presigned_url"` // S3 presigned download URL
|
|
||||||
FileSize int64 `json:"file_size"` // File size in bytes
|
|
||||||
ExpiresIn int `json:"expires_in"` // URL expiration time in seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
// Confirm upload completion
|
|
||||||
ConfirmUploadReq {
|
|
||||||
FileId int64 `json:"file_id"` // File ID to confirm
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfirmUploadResp {
|
|
||||||
Success bool `json:"success"` // Upload confirmation status
|
|
||||||
Message string `json:"message"` // Status message
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// ============= Post Types =============
|
|
||||||
type (
|
|
||||||
// Create post request
|
|
||||||
CreatePostReq {
|
|
||||||
Title string `json:"title"` // Post title
|
|
||||||
Content string `json:"content"` // Post content
|
|
||||||
Hashtags []string `json:"hashtags,optional"` // Associated hashtags
|
|
||||||
}
|
|
||||||
|
|
||||||
CreatePostResp {
|
|
||||||
PostId int64 `json:"post_id"` // Created post ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update post request
|
|
||||||
UpdatePostReq {
|
|
||||||
PostId int64 `path:"post_id"` // Post ID to update
|
|
||||||
Title string `json:"title,optional"` // New title
|
|
||||||
Content string `json:"content,optional"` // New content
|
|
||||||
Hashtags []string `json:"hashtags,optional"` // New hashtags (replaces all)
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdatePostResp {
|
|
||||||
Success bool `json:"success"` // Update status
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete post request
|
|
||||||
DeletePostReq {
|
|
||||||
PostId int64 `path:"post_id"` // Post ID to delete
|
|
||||||
}
|
|
||||||
|
|
||||||
DeletePostResp {
|
|
||||||
Success bool `json:"success"` // Delete status
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get post detail request
|
|
||||||
GetPostReq {
|
|
||||||
PostId int64 `path:"post_id"` // Post ID to retrieve
|
|
||||||
}
|
|
||||||
|
|
||||||
PostDetail {
|
|
||||||
PostId int64 `json:"post_id"` // Post ID
|
|
||||||
Title string `json:"title"` // Post title
|
|
||||||
Content string `json:"content"` // Post content
|
|
||||||
ViewCount int64 `json:"view_count"` // View count
|
|
||||||
Hashtags []Hashtag `json:"hashtags"` // Associated hashtags
|
|
||||||
CreatedAt string `json:"created_at"` // Creation timestamp
|
|
||||||
UpdatedAt string `json:"updated_at"` // Last update timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
GetPostResp {
|
|
||||||
Post PostDetail `json:"post"` // Post detail
|
|
||||||
}
|
|
||||||
|
|
||||||
// List posts request
|
|
||||||
ListPostsReq {
|
|
||||||
Page int `form:"page,default=1"` // Page number
|
|
||||||
PageSize int `form:"page_size,default=10"` // Items per page
|
|
||||||
Hashtag string `form:"hashtag,optional"` // Filter by hashtag name
|
|
||||||
SortBy string `form:"sort_by,default=created_at,options=created_at|view_count|updated_at"` // Sort field
|
|
||||||
}
|
|
||||||
|
|
||||||
PostItem {
|
|
||||||
PostId int64 `json:"post_id"` // Post ID
|
|
||||||
Title string `json:"title"` // Post title
|
|
||||||
ViewCount int64 `json:"view_count"` // View count
|
|
||||||
Hashtags []Hashtag `json:"hashtags"` // Associated hashtags
|
|
||||||
CreatedAt string `json:"created_at"` // Creation timestamp
|
|
||||||
UpdatedAt string `json:"updated_at"` // Last update timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
ListPostsResp {
|
|
||||||
Posts []PostItem `json:"posts"` // List of posts
|
|
||||||
Total int64 `json:"total"` // Total count
|
|
||||||
Page int `json:"page"` // Current page
|
|
||||||
PageSize int `json:"page_size"` // Items per page
|
|
||||||
TotalPages int `json:"total_pages"` // Total pages
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// ============= Hashtag Types =============
|
|
||||||
type (
|
|
||||||
Hashtag {
|
|
||||||
HashtagId int64 `json:"hashtag_id"` // Hashtag ID
|
|
||||||
Name string `json:"name"` // Hashtag name
|
|
||||||
UsageCount int64 `json:"usage_count"` // Usage count
|
|
||||||
}
|
|
||||||
|
|
||||||
// List hashtags request
|
|
||||||
ListHashtagsReq {
|
|
||||||
Page int `form:"page,default=1"` // Page number
|
|
||||||
PageSize int `form:"page_size,default=20"` // Items per page
|
|
||||||
SortBy string `form:"sort_by,default=usage_count,options=usage_count|created_at|name"` // Sort field
|
|
||||||
}
|
|
||||||
|
|
||||||
ListHashtagsResp {
|
|
||||||
Hashtags []Hashtag `json:"hashtags"` // List of hashtags
|
|
||||||
Total int64 `json:"total"` // Total count
|
|
||||||
Page int `json:"page"` // Current page
|
|
||||||
PageSize int `json:"page_size"` // Items per page
|
|
||||||
TotalPages int `json:"total_pages"` // Total pages
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get popular hashtags
|
|
||||||
GetPopularHashtagsReq {
|
|
||||||
Limit int `form:"limit,default=10"` // Number of hashtags to return
|
|
||||||
}
|
|
||||||
|
|
||||||
GetPopularHashtagsResp {
|
|
||||||
Hashtags []Hashtag `json:"hashtags"` // Popular hashtags
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// ============= Service Definition =============
|
|
||||||
@server (
|
|
||||||
prefix: /api/v1/blog
|
|
||||||
group: file
|
|
||||||
)
|
|
||||||
service Blog {
|
|
||||||
@doc "Generate presigned URL for file upload"
|
|
||||||
@handler generateUploadUrl
|
|
||||||
post /files/upload/url (GenerateUploadUrlReq) returns (GenerateUploadUrlResp)
|
|
||||||
|
|
||||||
@doc "Generate presigned URL for file download"
|
|
||||||
@handler generateDownloadUrl
|
|
||||||
get /files/download/:file_id (GenerateDownloadUrlReq) returns (GenerateDownloadUrlResp)
|
|
||||||
|
|
||||||
@doc "Confirm file upload completion"
|
|
||||||
@handler confirmUpload
|
|
||||||
post /files/upload/confirm (ConfirmUploadReq) returns (ConfirmUploadResp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@server (
|
@server (
|
||||||
prefix: /api/v1/blog
|
prefix: /api/v1
|
||||||
group: post
|
|
||||||
)
|
)
|
||||||
service Blog {
|
service Blog {
|
||||||
@doc "Create a new blog post"
|
@handler uploadFile
|
||||||
@handler createPost
|
post /files/upload (UploadReq) returns (UploadResp)
|
||||||
post /posts (CreatePostReq) returns (CreatePostResp)
|
|
||||||
|
|
||||||
@doc "Update an existing blog post"
|
@handler downloadFile
|
||||||
@handler updatePost
|
get /files/download (DownloadReq) returns (DownloadResp)
|
||||||
put /posts/:post_id (UpdatePostReq) returns (UpdatePostResp)
|
|
||||||
|
|
||||||
@doc "Delete a blog post"
|
@handler previewFile
|
||||||
@handler deletePost
|
get /files/preview (DownloadReq) returns (DownloadResp)
|
||||||
delete /posts/:post_id (DeletePostReq) returns (DeletePostResp)
|
|
||||||
|
|
||||||
@doc "Get blog post detail"
|
|
||||||
@handler getPost
|
|
||||||
get /posts/:post_id (GetPostReq) returns (GetPostResp)
|
|
||||||
|
|
||||||
@doc "List blog posts with pagination and filtering"
|
|
||||||
@handler listPosts
|
|
||||||
get /posts (ListPostsReq) returns (ListPostsResp)
|
|
||||||
}
|
|
||||||
|
|
||||||
@server (
|
|
||||||
prefix: /api/v1/blog
|
|
||||||
group: hashtag
|
|
||||||
)
|
|
||||||
service Blog {
|
|
||||||
@doc "List all hashtags with pagination"
|
|
||||||
@handler listHashtags
|
|
||||||
get /hashtags (ListHashtagsReq) returns (ListHashtagsResp)
|
|
||||||
|
|
||||||
@doc "Get popular hashtags"
|
|
||||||
@handler getPopularHashtags
|
|
||||||
get /hashtags/popular (GetPopularHashtagsReq) returns (GetPopularHashtagsResp)
|
|
||||||
}
|
|
||||||
|
|
||||||
@server (
|
|
||||||
prefix: /api/v1/blog
|
|
||||||
group: common
|
|
||||||
)
|
|
||||||
service Blog {
|
|
||||||
@doc "Health check endpoint"
|
|
||||||
@handler ping
|
|
||||||
get /ping
|
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,16 @@
|
|||||||
-- Files table: stores uploaded file metadata
|
|
||||||
CREATE TABLE IF NOT EXISTS files (
|
CREATE TABLE IF NOT EXISTS files (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL,
|
||||||
file_name VARCHAR(255) NOT NULL,
|
file_name VARCHAR(255) NOT NULL,
|
||||||
file_key VARCHAR(500) NOT NULL UNIQUE,
|
file_key VARCHAR(500) NOT NULL UNIQUE,
|
||||||
byte_size BIGINT NOT NULL,
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Index for looking up files by key (most common query)
|
COMMENT ON TABLE files IS 'Files table for storing uploaded files';
|
||||||
CREATE INDEX IF NOT EXISTS idx_files_file_key ON files(file_key);
|
|
||||||
|
|
||||||
-- Index for sorting files by creation date
|
COMMENT ON COLUMN files.id IS 'Unique identifier for the file';
|
||||||
CREATE INDEX IF NOT EXISTS idx_files_created_at ON files(created_at DESC);
|
COMMENT ON COLUMN files.file_name IS 'Name of the uploaded file';
|
||||||
|
COMMENT ON COLUMN files.file_key IS 'Unique key for the file storage';
|
||||||
-- Index for file size queries
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_files_byte_size ON files(byte_size);
|
|
||||||
|
|
||||||
-- Comments on columns
|
|
||||||
COMMENT ON TABLE files IS 'File metadata table for uploaded files';
|
|
||||||
COMMENT ON COLUMN files.id IS 'Primary key, auto-incrementing file ID';
|
|
||||||
COMMENT ON COLUMN files.file_name IS 'Original name of the uploaded file';
|
|
||||||
COMMENT ON COLUMN files.file_key IS 'Unique storage key/path for the file';
|
|
||||||
COMMENT ON COLUMN files.byte_size IS 'File size in bytes';
|
|
||||||
COMMENT ON COLUMN files.created_at IS 'Timestamp when the file was uploaded';
|
COMMENT ON COLUMN files.created_at IS 'Timestamp when the file was uploaded';
|
||||||
|
|
||||||
|
CREATE INDEX idx_files_created_at ON files(created_at);
|
||||||
@@ -1,23 +1,15 @@
|
|||||||
-- Hashtags table: stores unique hashtag information
|
|
||||||
CREATE TABLE IF NOT EXISTS hashtags (
|
CREATE TABLE IF NOT EXISTS hashtags (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL,
|
||||||
name VARCHAR(50) NOT NULL UNIQUE,
|
name VARCHAR(50) NOT NULL UNIQUE,
|
||||||
usage_count BIGINT DEFAULT 0,
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Index for looking up hashtags by name (most common query)
|
COMMENT ON TABLE hashtags IS 'Hashtags table for storing unique hashtag names';
|
||||||
CREATE INDEX IF NOT EXISTS idx_hashtags_name ON hashtags(name);
|
|
||||||
|
|
||||||
-- Index for sorting hashtags by popularity
|
COMMENT ON COLUMN hashtags.id IS 'Unique identifier for the hashtag';
|
||||||
CREATE INDEX IF NOT EXISTS idx_hashtags_usage_count ON hashtags(usage_count DESC);
|
COMMENT ON COLUMN hashtags.name IS 'Name of the hashtag';
|
||||||
|
COMMENT ON COLUMN hashtags.created_at IS 'Timestamp when the hashtag was created';
|
||||||
|
|
||||||
-- Index for trending hashtags (recent + popular)
|
CREATE INDEX idx_hashtags_name ON hashtags(name);
|
||||||
CREATE INDEX IF NOT EXISTS idx_hashtags_created_usage ON hashtags(created_at DESC, usage_count DESC);
|
CREATE INDEX idx_hashtags_created_at ON hashtags(created_at);
|
||||||
|
|
||||||
-- Comments on columns
|
|
||||||
COMMENT ON TABLE hashtags IS 'Hashtags table for categorizing posts';
|
|
||||||
COMMENT ON COLUMN hashtags.id IS 'Primary key, auto-incrementing hashtag ID';
|
|
||||||
COMMENT ON COLUMN hashtags.name IS 'Unique hashtag name';
|
|
||||||
COMMENT ON COLUMN hashtags.usage_count IS 'Number of times the hashtag has been used';
|
|
||||||
COMMENT ON COLUMN hashtags.created_at IS 'Timestamp when the hashtag was first created';
|
|
||||||
@@ -1,23 +1,16 @@
|
|||||||
-- Post_hashtags junction table: many-to-many relationship between posts and hashtags
|
|
||||||
CREATE TABLE IF NOT EXISTS post_hashtags (
|
CREATE TABLE IF NOT EXISTS post_hashtags (
|
||||||
post_id BIGINT NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
|
post_id BIGINT NOT NULL,
|
||||||
hashtag_id BIGINT NOT NULL REFERENCES hashtags(id) ON DELETE CASCADE,
|
hashtag_id BIGINT NOT NULL,
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
PRIMARY KEY (post_id, hashtag_id)
|
PRIMARY KEY (post_id, hashtag_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Index for finding all posts with a specific hashtag
|
COMMENT ON TABLE post_hashtags IS 'Junction table linking posts and hashtags for many-to-many relationship';
|
||||||
CREATE INDEX IF NOT EXISTS idx_post_hashtags_hashtag_id ON post_hashtags(hashtag_id, post_id);
|
|
||||||
|
|
||||||
-- Index for finding all hashtags for a specific post
|
COMMENT ON COLUMN post_hashtags.post_id IS 'Reference to the post id';
|
||||||
CREATE INDEX IF NOT EXISTS idx_post_hashtags_post_id ON post_hashtags(post_id, hashtag_id);
|
COMMENT ON COLUMN post_hashtags.hashtag_id IS 'Reference to the hashtag id';
|
||||||
|
COMMENT ON COLUMN post_hashtags.created_at IS 'Timestamp when the association was created';
|
||||||
|
|
||||||
-- Index for sorting by creation date
|
CREATE INDEX idx_post_hashtags_post_id ON post_hashtags(post_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_post_hashtags_created_at ON post_hashtags(created_at DESC);
|
CREATE INDEX idx_post_hashtags_hashtag_id ON post_hashtags(hashtag_id);
|
||||||
|
CREATE INDEX idx_post_hashtags_created_at ON post_hashtags(created_at);
|
||||||
-- Comments on columns
|
|
||||||
COMMENT ON TABLE post_hashtags IS 'Junction table linking posts and hashtags';
|
|
||||||
COMMENT ON COLUMN post_hashtags.post_id IS 'Foreign key referencing posts table';
|
|
||||||
COMMENT ON COLUMN post_hashtags.hashtag_id IS 'Foreign key referencing hashtags table';
|
|
||||||
COMMENT ON COLUMN post_hashtags.created_at IS 'Timestamp when the hashtag was associated with the post';
|
|
||||||
@@ -1,30 +1,21 @@
|
|||||||
-- Posts table: stores blog post information
|
|
||||||
CREATE TABLE IF NOT EXISTS posts (
|
CREATE TABLE IF NOT EXISTS posts (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL,
|
||||||
title VARCHAR(255) NOT NULL,
|
title VARCHAR(255) NOT NULL,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL,
|
||||||
view_count BIGINT DEFAULT 0,
|
cover_id BIGINT,
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Index for sorting posts by creation date
|
COMMENT ON TABLE posts IS 'Blog posts table';
|
||||||
CREATE INDEX IF NOT EXISTS idx_posts_created_at ON posts(created_at DESC);
|
|
||||||
|
|
||||||
-- Index for sorting posts by view count (popular posts)
|
COMMENT ON COLUMN posts.id IS 'Unique identifier for the post';
|
||||||
CREATE INDEX IF NOT EXISTS idx_posts_view_count ON posts(view_count DESC);
|
COMMENT ON COLUMN posts.title IS 'Title of the blog post';
|
||||||
|
COMMENT ON COLUMN posts.content IS 'Content of the blog post';
|
||||||
-- Index for sorting posts by update date
|
COMMENT ON COLUMN posts.cover_id IS 'Reference to the cover image file id';
|
||||||
CREATE INDEX IF NOT EXISTS idx_posts_updated_at ON posts(updated_at DESC);
|
|
||||||
|
|
||||||
-- Combined index for pagination queries
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_posts_created_view ON posts(created_at DESC, view_count DESC);
|
|
||||||
|
|
||||||
-- Comments on columns
|
|
||||||
COMMENT ON TABLE posts IS 'Blog posts table containing article information';
|
|
||||||
COMMENT ON COLUMN posts.id IS 'Primary key, auto-incrementing post ID';
|
|
||||||
COMMENT ON COLUMN posts.title IS 'Post title';
|
|
||||||
COMMENT ON COLUMN posts.content IS 'Post content in text format';
|
|
||||||
COMMENT ON COLUMN posts.view_count IS 'Number of times the post has been viewed';
|
|
||||||
COMMENT ON COLUMN posts.created_at IS 'Timestamp when the post was created';
|
COMMENT ON COLUMN posts.created_at IS 'Timestamp when the post was created';
|
||||||
COMMENT ON COLUMN posts.updated_at IS 'Timestamp when the post was last updated';
|
COMMENT ON COLUMN posts.updated_at IS 'Timestamp when the post was last updated';
|
||||||
|
|
||||||
|
CREATE INDEX idx_posts_created_at ON posts(created_at);
|
||||||
|
CREATE INDEX idx_posts_cover_id ON posts(cover_id);
|
||||||
21
ddl/tmpfiles.sql
Normal file
21
ddl/tmpfiles.sql
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS tmpfiles (
|
||||||
|
id BIGSERIAL,
|
||||||
|
file_name VARCHAR(255) NOT NULL,
|
||||||
|
key VARCHAR(500) NOT NULL UNIQUE,
|
||||||
|
presigned_url TEXT NOT NULL,
|
||||||
|
expiration TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMENT ON TABLE tmpfiles IS 'Temporary files table for storing files with presigned URLs and expiration times';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN tmpfiles.id IS 'Unique identifier for the temporary file';
|
||||||
|
COMMENT ON COLUMN tmpfiles.file_name IS 'Name of the temporary file';
|
||||||
|
COMMENT ON COLUMN tmpfiles.key IS 'Unique key for the temporary file';
|
||||||
|
COMMENT ON COLUMN tmpfiles.presigned_url IS 'Presigned URL for accessing the temporary file';
|
||||||
|
COMMENT ON COLUMN tmpfiles.expiration IS 'Expiration timestamp for the temporary file';
|
||||||
|
COMMENT ON COLUMN tmpfiles.created_at IS 'Timestamp when the temporary file was created';
|
||||||
|
|
||||||
|
CREATE INDEX idx_tmpfiles_expiration ON tmpfiles(expiration);
|
||||||
|
CREATE INDEX idx_tmpfiles_created_at ON tmpfiles(created_at);
|
||||||
Reference in New Issue
Block a user