256 lines
8.4 KiB
PL/PgSQL
256 lines
8.4 KiB
PL/PgSQL
-- ============================================
|
|
-- 文档版本管理 RPC 函数(第4版 - 显式类型转换)
|
|
-- 功能:支持同名文档的版本管理和历史查询
|
|
-- 修复:所有字段显式转换为函数返回类型
|
|
-- 创建时间:2025-11-14
|
|
-- ============================================
|
|
|
|
-- ====================
|
|
-- 删除旧函数
|
|
-- ====================
|
|
DROP FUNCTION IF EXISTS documents_get_latest_documents_with_version_info(integer,integer,integer,text,text,integer[],integer,text,text,text);
|
|
DROP FUNCTION IF EXISTS documents_count_latest_documents_with_filters(integer,text,text,integer[],integer,text,text,text);
|
|
DROP FUNCTION IF EXISTS documents_get_document_history(text,integer,integer);
|
|
|
|
|
|
-- ====================
|
|
-- 1. 获取最新版本的文档列表(带版本信息)
|
|
-- ====================
|
|
CREATE FUNCTION documents_get_latest_documents_with_version_info(
|
|
p_user_id integer,
|
|
p_page integer DEFAULT 1,
|
|
p_page_size integer DEFAULT 10,
|
|
p_search_name text DEFAULT NULL,
|
|
p_search_document_number text DEFAULT NULL,
|
|
p_search_document_types integer[] DEFAULT NULL,
|
|
p_search_audit_status integer DEFAULT NULL,
|
|
p_search_file_status text DEFAULT NULL,
|
|
p_search_date_from text DEFAULT NULL,
|
|
p_search_date_to text DEFAULT NULL
|
|
)
|
|
RETURNS TABLE (
|
|
id integer,
|
|
name text,
|
|
document_number text,
|
|
type_id integer,
|
|
type_name text,
|
|
file_size integer,
|
|
audit_status integer,
|
|
status text,
|
|
false_count bigint,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
path text,
|
|
is_test_document boolean,
|
|
ocr_result jsonb,
|
|
history_count bigint,
|
|
previous_issues bigint
|
|
) AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
WITH latest_docs AS (
|
|
-- 使用 DISTINCT ON 获取每个文档名称的最新版本
|
|
SELECT DISTINCT ON (d.name)
|
|
d.id,
|
|
d.name,
|
|
d.user_id,
|
|
d.created_at
|
|
FROM documents d
|
|
WHERE d.user_id = p_user_id
|
|
-- 文档名称搜索
|
|
AND (p_search_name IS NULL OR d.name ILIKE '%' || p_search_name || '%')
|
|
-- 文档编号搜索
|
|
AND (p_search_document_number IS NULL OR d.document_number ILIKE '%' || p_search_document_number || '%')
|
|
-- 文档类型筛选
|
|
AND (p_search_document_types IS NULL OR d.type_id = ANY(p_search_document_types))
|
|
-- 审核状态筛选
|
|
AND (p_search_audit_status IS NULL OR d.audit_status = p_search_audit_status)
|
|
-- 文件状态筛选
|
|
AND (p_search_file_status IS NULL OR d.status = p_search_file_status)
|
|
-- 日期范围筛选
|
|
AND (p_search_date_from IS NULL OR d.created_at >= p_search_date_from::timestamp)
|
|
AND (p_search_date_to IS NULL OR d.created_at <= p_search_date_to::timestamp)
|
|
ORDER BY d.name, d.created_at DESC
|
|
)
|
|
SELECT
|
|
d.id::integer,
|
|
d.name::text,
|
|
d.document_number::text,
|
|
d.type_id::integer,
|
|
COALESCE(dt.name::text, '') as type_name,
|
|
d.file_size::integer,
|
|
d.audit_status::integer,
|
|
d.status::text,
|
|
-- 计算当前文档的问题数量(从 evaluation_results 表统计)
|
|
COALESCE((
|
|
SELECT COUNT(*)
|
|
FROM evaluation_results er
|
|
WHERE er.document_id = d.id
|
|
AND (er.evaluated_results ->> 'result')::text = 'false'
|
|
), 0)::bigint as false_count,
|
|
d.created_at::timestamp with time zone,
|
|
d.updated_at::timestamp with time zone,
|
|
d.path::text,
|
|
d.is_test_document::boolean,
|
|
d.ocr_result::jsonb,
|
|
-- 计算历史版本数量(不包含当前版本)
|
|
COALESCE((
|
|
SELECT COUNT(*)
|
|
FROM documents d2
|
|
WHERE d2.name = d.name
|
|
AND d2.user_id = d.user_id
|
|
AND d2.id != d.id
|
|
), 0)::bigint as history_count,
|
|
-- 获取上一个版本的问题数量
|
|
COALESCE((
|
|
SELECT COUNT(*)
|
|
FROM evaluation_results er2
|
|
WHERE er2.document_id = (
|
|
SELECT d3.id
|
|
FROM documents d3
|
|
WHERE d3.name = d.name
|
|
AND d3.user_id = d.user_id
|
|
AND d3.created_at < d.created_at
|
|
ORDER BY d3.created_at DESC
|
|
LIMIT 1
|
|
)
|
|
AND (er2.evaluated_results ->> 'result')::text = 'false'
|
|
), 0)::bigint as previous_issues
|
|
FROM documents d
|
|
INNER JOIN latest_docs ld ON d.id = ld.id
|
|
LEFT JOIN document_types dt ON d.type_id = dt.id
|
|
ORDER BY d.created_at DESC
|
|
LIMIT p_page_size OFFSET (p_page - 1) * p_page_size;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION documents_get_latest_documents_with_version_info IS '获取最新版本的文档列表,包含历史版本数量和上一个版本的问题数量(从 evaluation_results 表计算)';
|
|
|
|
|
|
-- ====================
|
|
-- 2. 统计最新版本文档的总数
|
|
-- ====================
|
|
CREATE FUNCTION documents_count_latest_documents_with_filters(
|
|
p_user_id integer,
|
|
p_search_name text DEFAULT NULL,
|
|
p_search_document_number text DEFAULT NULL,
|
|
p_search_document_types integer[] DEFAULT NULL,
|
|
p_search_audit_status integer DEFAULT NULL,
|
|
p_search_file_status text DEFAULT NULL,
|
|
p_search_date_from text DEFAULT NULL,
|
|
p_search_date_to text DEFAULT NULL
|
|
)
|
|
RETURNS integer AS $$
|
|
DECLARE
|
|
doc_count integer;
|
|
BEGIN
|
|
WITH latest_docs AS (
|
|
SELECT DISTINCT ON (d.name)
|
|
d.id
|
|
FROM documents d
|
|
WHERE d.user_id = p_user_id
|
|
AND (p_search_name IS NULL OR d.name ILIKE '%' || p_search_name || '%')
|
|
AND (p_search_document_number IS NULL OR d.document_number ILIKE '%' || p_search_document_number || '%')
|
|
AND (p_search_document_types IS NULL OR d.type_id = ANY(p_search_document_types))
|
|
AND (p_search_audit_status IS NULL OR d.audit_status = p_search_audit_status)
|
|
AND (p_search_file_status IS NULL OR d.status = p_search_file_status)
|
|
AND (p_search_date_from IS NULL OR d.created_at >= p_search_date_from::timestamp)
|
|
AND (p_search_date_to IS NULL OR d.created_at <= p_search_date_to::timestamp)
|
|
ORDER BY d.name, d.created_at DESC
|
|
)
|
|
SELECT COUNT(*)::integer INTO doc_count FROM latest_docs;
|
|
|
|
RETURN doc_count;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION documents_count_latest_documents_with_filters IS '统计符合条件的最新版本文档总数(用于分页)';
|
|
|
|
|
|
-- ====================
|
|
-- 3. 获取文档的历史版本列表
|
|
-- ====================
|
|
CREATE FUNCTION documents_get_document_history(
|
|
p_document_name text,
|
|
p_user_id integer,
|
|
p_exclude_id integer
|
|
)
|
|
RETURNS TABLE (
|
|
id integer,
|
|
name text,
|
|
document_number text,
|
|
type_id integer,
|
|
type_name text,
|
|
file_size integer,
|
|
audit_status integer,
|
|
status text,
|
|
false_count bigint,
|
|
created_at timestamp with time zone,
|
|
updated_at timestamp with time zone,
|
|
path text,
|
|
is_test_document boolean,
|
|
ocr_result jsonb
|
|
) AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT
|
|
d.id::integer,
|
|
d.name::text,
|
|
d.document_number::text,
|
|
d.type_id::integer,
|
|
COALESCE(dt.name::text, '') as type_name,
|
|
d.file_size::integer,
|
|
d.audit_status::integer,
|
|
d.status::text,
|
|
-- 计算每个历史版本的问题数量
|
|
COALESCE((
|
|
SELECT COUNT(*)
|
|
FROM evaluation_results er
|
|
WHERE er.document_id = d.id
|
|
AND (er.evaluated_results ->> 'result')::text = 'false'
|
|
), 0)::bigint as false_count,
|
|
d.created_at::timestamp with time zone,
|
|
d.updated_at::timestamp with time zone,
|
|
d.path::text,
|
|
d.is_test_document::boolean,
|
|
d.ocr_result::jsonb
|
|
FROM documents d
|
|
LEFT JOIN document_types dt ON d.type_id = dt.id
|
|
WHERE d.name = p_document_name
|
|
AND d.user_id = p_user_id
|
|
AND d.id != p_exclude_id
|
|
ORDER BY d.created_at DESC;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION documents_get_document_history IS '获取指定文档名称的所有历史版本(不包含指定的当前版本ID),从 evaluation_results 表计算问题数量';
|
|
|
|
|
|
-- ====================
|
|
-- 4. 创建索引优化查询性能
|
|
-- ====================
|
|
|
|
-- 复合索引:user_id + name + created_at
|
|
CREATE INDEX IF NOT EXISTS idx_documents_user_name_created
|
|
ON documents(user_id, name, created_at DESC);
|
|
|
|
-- 复合索引:name + user_id + created_at
|
|
CREATE INDEX IF NOT EXISTS idx_documents_name_user_created
|
|
ON documents(name, user_id, created_at DESC);
|
|
|
|
-- 单列索引:created_at
|
|
CREATE INDEX IF NOT EXISTS idx_documents_created_at
|
|
ON documents(created_at DESC);
|
|
|
|
-- 单列索引:status
|
|
CREATE INDEX IF NOT EXISTS idx_documents_status
|
|
ON documents(status);
|
|
|
|
-- evaluation_results 的 document_id
|
|
CREATE INDEX IF NOT EXISTS idx_evaluation_results_document_id
|
|
ON evaluation_results(document_id);
|
|
|
|
-- evaluation_results 的 evaluated_results->>'result'
|
|
CREATE INDEX IF NOT EXISTS idx_evaluation_results_result
|
|
ON evaluation_results((evaluated_results ->> 'result'));
|