增加项目的各个功能

This commit is contained in:
qiaoxinjiu
2026-05-07 19:21:19 +08:00
parent aba1618f89
commit ee6cd4ae66
121 changed files with 9346 additions and 43 deletions

534
数据库语句 Normal file
View File

@@ -0,0 +1,534 @@
-- =========================================================
-- 测试管理模块数据库初始化脚本_time 字段版本)
-- 适用数据库PostgreSQL
-- 说明:
-- 1. 本脚本与当前后端代码字段保持一致
-- 2. 所有时间字段统一使用 *_time 后缀
-- 3. 主表包含 is_delete 逻辑删除字段
-- =========================================================
-- =========================================================
-- 一、项目相关
-- =========================================================
-- -------------------------
-- 1. 项目表
-- -------------------------
CREATE TABLE IF NOT EXISTS project (
id BIGSERIAL PRIMARY KEY,
key VARCHAR(32) UNIQUE NOT NULL,
name VARCHAR(128) NOT NULL,
description TEXT,
department VARCHAR(64),
status SMALLINT DEFAULT 1,
config JSONB DEFAULT '{}'::jsonb,
created_by BIGINT,
is_delete INTEGER DEFAULT 0,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE project IS '项目表';
COMMENT ON COLUMN project.id IS '主键ID';
COMMENT ON COLUMN project.key IS '项目唯一标识,如 XP2024';
COMMENT ON COLUMN project.name IS '项目名称';
COMMENT ON COLUMN project.description IS '项目描述';
COMMENT ON COLUMN project.department IS '所属部门';
COMMENT ON COLUMN project.status IS '项目状态1启用 0禁用';
COMMENT ON COLUMN project.config IS '扩展配置JSON格式';
COMMENT ON COLUMN project.created_by IS '创建人';
COMMENT ON COLUMN project.is_delete IS '逻辑删除标记0未删除 1已删除';
COMMENT ON COLUMN project.created_time IS '创建时间';
COMMENT ON COLUMN project.updated_time IS '更新时间';
CREATE INDEX IF NOT EXISTS idx_project_status ON project(status);
CREATE INDEX IF NOT EXISTS idx_project_is_delete ON project(is_delete);
-- -------------------------
-- 2. 项目成员表
-- -------------------------
CREATE TABLE IF NOT EXISTS project_member (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
user_id BIGINT NOT NULL,
role SMALLINT NOT NULL,
joined_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE project_member IS '项目成员表';
COMMENT ON COLUMN project_member.id IS '主键ID';
COMMENT ON COLUMN project_member.project_id IS '项目ID';
COMMENT ON COLUMN project_member.user_id IS '用户ID';
COMMENT ON COLUMN project_member.role IS '角色1测试经理 2测试工程师 3开发工程师 4访客';
COMMENT ON COLUMN project_member.joined_time IS '加入时间';
CREATE UNIQUE INDEX IF NOT EXISTS uk_project_member ON project_member(project_id, user_id);
CREATE INDEX IF NOT EXISTS idx_member_user ON project_member(user_id);
CREATE INDEX IF NOT EXISTS idx_member_project_id ON project_member(project_id);
-- -------------------------
-- 3. 环境配置表
-- -------------------------
CREATE TABLE IF NOT EXISTS environment (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
name VARCHAR(64) NOT NULL,
variables JSONB NOT NULL,
is_encrypted BOOLEAN DEFAULT FALSE,
is_delete INTEGER DEFAULT 0,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE environment IS '环境配置表';
COMMENT ON COLUMN environment.id IS '主键ID';
COMMENT ON COLUMN environment.project_id IS '项目ID';
COMMENT ON COLUMN environment.name IS '环境名称,如 dev/test/staging/prod';
COMMENT ON COLUMN environment.variables IS '环境变量配置JSON格式';
COMMENT ON COLUMN environment.is_encrypted IS '敏感信息是否已加密';
COMMENT ON COLUMN environment.is_delete IS '逻辑删除标记0未删除 1已删除';
COMMENT ON COLUMN environment.created_time IS '创建时间';
CREATE INDEX IF NOT EXISTS idx_environment_project_id ON environment(project_id);
CREATE INDEX IF NOT EXISTS idx_environment_is_delete ON environment(is_delete);
-- -------------------------
-- 4. 产品表
-- -------------------------
CREATE TABLE IF NOT EXISTS product (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(128) NOT NULL,
code VARCHAR(64) UNIQUE NOT NULL,
description TEXT,
status SMALLINT DEFAULT 1,
is_delete INTEGER DEFAULT 0,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE product IS '产品表';
COMMENT ON COLUMN product.id IS '主键ID';
COMMENT ON COLUMN product.name IS '产品名称';
COMMENT ON COLUMN product.code IS '产品编码';
COMMENT ON COLUMN product.description IS '产品描述';
COMMENT ON COLUMN product.status IS '产品状态1启用 0禁用';
COMMENT ON COLUMN product.is_delete IS '逻辑删除标记0未删除 1已删除';
COMMENT ON COLUMN product.created_time IS '创建时间';
COMMENT ON COLUMN product.updated_time IS '更新时间';
CREATE INDEX IF NOT EXISTS idx_product_status ON product(status);
CREATE INDEX IF NOT EXISTS idx_product_is_delete ON product(is_delete);
-- =========================================================
-- 二、用例相关
-- =========================================================
-- -------------------------
-- 4. 模块表
-- -------------------------
CREATE TABLE IF NOT EXISTS module (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
parent_id BIGINT DEFAULT 0,
name VARCHAR(128) NOT NULL,
sort_order INTEGER DEFAULT 0,
path VARCHAR(512),
is_delete INTEGER DEFAULT 0
);
COMMENT ON TABLE module IS '模块树表,支持多层级模块结构';
COMMENT ON COLUMN module.id IS '主键ID';
COMMENT ON COLUMN module.project_id IS '项目ID';
COMMENT ON COLUMN module.parent_id IS '父模块ID0表示根节点';
COMMENT ON COLUMN module.name IS '模块名称';
COMMENT ON COLUMN module.sort_order IS '排序值';
COMMENT ON COLUMN module.path IS '模块路径,如 /1/23/45';
COMMENT ON COLUMN module.is_delete IS '逻辑删除标记0未删除 1已删除';
CREATE INDEX IF NOT EXISTS idx_module_project ON module(project_id);
CREATE INDEX IF NOT EXISTS idx_module_parent_id ON module(parent_id);
CREATE INDEX IF NOT EXISTS idx_module_is_delete ON module(is_delete);
-- -------------------------
-- 5. 用例表
-- -------------------------
CREATE TABLE IF NOT EXISTS test_case (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
module_id BIGINT REFERENCES module(id) ON DELETE SET NULL,
case_key VARCHAR(64) NOT NULL,
title VARCHAR(255) NOT NULL,
preconditions TEXT,
steps JSONB NOT NULL DEFAULT '[]'::jsonb,
priority SMALLINT DEFAULT 2,
case_type SMALLINT DEFAULT 1,
tags VARCHAR(64)[] DEFAULT '{}'::varchar[],
status SMALLINT DEFAULT 1,
created_by BIGINT,
is_delete INTEGER DEFAULT 0,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE test_case IS '测试用例表';
COMMENT ON COLUMN test_case.id IS '主键ID';
COMMENT ON COLUMN test_case.project_id IS '项目ID';
COMMENT ON COLUMN test_case.module_id IS '所属模块ID';
COMMENT ON COLUMN test_case.case_key IS '项目内唯一编号,如 TC-001';
COMMENT ON COLUMN test_case.title IS '用例标题';
COMMENT ON COLUMN test_case.preconditions IS '前置条件';
COMMENT ON COLUMN test_case.steps IS '测试步骤JSON数组';
COMMENT ON COLUMN test_case.priority IS '优先级0P0 1P1 2P2 3P3';
COMMENT ON COLUMN test_case.case_type IS '用例类型1功能 2性能 3安全 4接口';
COMMENT ON COLUMN test_case.tags IS '标签数组';
COMMENT ON COLUMN test_case.status IS '状态1正常 2已废弃 3评审中';
COMMENT ON COLUMN test_case.created_by IS '创建人';
COMMENT ON COLUMN test_case.is_delete IS '逻辑删除标记0未删除 1已删除';
COMMENT ON COLUMN test_case.created_time IS '创建时间';
COMMENT ON COLUMN test_case.updated_time IS '更新时间';
CREATE INDEX IF NOT EXISTS idx_case_project ON test_case(project_id);
CREATE INDEX IF NOT EXISTS idx_case_module ON test_case(module_id);
CREATE INDEX IF NOT EXISTS idx_case_priority ON test_case(priority);
CREATE INDEX IF NOT EXISTS idx_case_status ON test_case(status);
CREATE INDEX IF NOT EXISTS idx_case_is_delete ON test_case(is_delete);
CREATE UNIQUE INDEX IF NOT EXISTS uk_test_case_project_case_key ON test_case(project_id, case_key);
-- -------------------------
-- 6. 用例快照表
-- -------------------------
CREATE TABLE IF NOT EXISTS case_snapshot (
id BIGSERIAL PRIMARY KEY,
case_id BIGINT NOT NULL REFERENCES test_case(id) ON DELETE CASCADE,
version INTEGER NOT NULL,
snapshot JSONB NOT NULL,
created_by BIGINT,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE case_snapshot IS '用例版本快照表';
COMMENT ON COLUMN case_snapshot.id IS '主键ID';
COMMENT ON COLUMN case_snapshot.case_id IS '用例ID';
COMMENT ON COLUMN case_snapshot.version IS '版本号';
COMMENT ON COLUMN case_snapshot.snapshot IS '完整快照内容';
COMMENT ON COLUMN case_snapshot.created_by IS '创建人';
COMMENT ON COLUMN case_snapshot.created_time IS '创建时间';
CREATE INDEX IF NOT EXISTS idx_case_snapshot_case_id ON case_snapshot(case_id);
CREATE UNIQUE INDEX IF NOT EXISTS uk_case_snapshot_case_version ON case_snapshot(case_id, version);
-- -------------------------
-- 7. 用例评审表
-- -------------------------
CREATE TABLE IF NOT EXISTS case_review (
id BIGSERIAL PRIMARY KEY,
case_id BIGINT NOT NULL REFERENCES test_case(id) ON DELETE CASCADE,
reviewer_id BIGINT NOT NULL,
status SMALLINT DEFAULT 0,
comments TEXT,
diff_content TEXT,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
reviewed_time TIMESTAMP
);
COMMENT ON TABLE case_review IS '用例评审表';
COMMENT ON COLUMN case_review.id IS '主键ID';
COMMENT ON COLUMN case_review.case_id IS '用例ID';
COMMENT ON COLUMN case_review.reviewer_id IS '评审人ID';
COMMENT ON COLUMN case_review.status IS '评审状态0待评审 1通过 2驳回 3建议修改';
COMMENT ON COLUMN case_review.comments IS '评审意见';
COMMENT ON COLUMN case_review.diff_content IS '变更差异内容通常为JSON diff字符串';
COMMENT ON COLUMN case_review.created_time IS '创建时间';
COMMENT ON COLUMN case_review.reviewed_time IS '评审时间';
CREATE INDEX IF NOT EXISTS idx_case_review_case_id ON case_review(case_id);
CREATE INDEX IF NOT EXISTS idx_case_review_reviewer_id ON case_review(reviewer_id);
-- =========================================================
-- 三、测试计划相关
-- =========================================================
-- -------------------------
-- 8. 测试计划表
-- -------------------------
CREATE TABLE IF NOT EXISTS test_plan (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
name VARCHAR(128) NOT NULL,
version VARCHAR(32),
description TEXT,
start_date DATE,
end_date DATE,
owner_id BIGINT,
status SMALLINT DEFAULT 0,
environment_id BIGINT REFERENCES environment(id),
is_delete INTEGER DEFAULT 0,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE test_plan IS '测试计划表';
COMMENT ON COLUMN test_plan.id IS '主键ID';
COMMENT ON COLUMN test_plan.project_id IS '项目ID';
COMMENT ON COLUMN test_plan.name IS '计划名称';
COMMENT ON COLUMN test_plan.version IS '测试版本号';
COMMENT ON COLUMN test_plan.description IS '计划描述';
COMMENT ON COLUMN test_plan.start_date IS '开始日期';
COMMENT ON COLUMN test_plan.end_date IS '结束日期';
COMMENT ON COLUMN test_plan.owner_id IS '负责人ID';
COMMENT ON COLUMN test_plan.status IS '计划状态0草稿 1进行中 2已完成 3已归档';
COMMENT ON COLUMN test_plan.environment_id IS '关联环境ID';
COMMENT ON COLUMN test_plan.is_delete IS '逻辑删除标记0未删除 1已删除';
COMMENT ON COLUMN test_plan.created_time IS '创建时间';
COMMENT ON COLUMN test_plan.updated_time IS '更新时间';
CREATE INDEX IF NOT EXISTS idx_test_plan_project_id ON test_plan(project_id);
CREATE INDEX IF NOT EXISTS idx_test_plan_status ON test_plan(status);
CREATE INDEX IF NOT EXISTS idx_test_plan_is_delete ON test_plan(is_delete);
-- -------------------------
-- 9. 计划用例表
-- -------------------------
CREATE TABLE IF NOT EXISTS plan_case (
id BIGSERIAL PRIMARY KEY,
plan_id BIGINT NOT NULL REFERENCES test_plan(id) ON DELETE CASCADE,
case_id BIGINT NOT NULL REFERENCES test_case(id),
assignee_id BIGINT,
round_no INTEGER DEFAULT 1,
status SMALLINT DEFAULT 0,
actual_result TEXT,
defect_links JSONB DEFAULT '[]'::jsonb,
attachments JSONB DEFAULT '[]'::jsonb,
executed_time TIMESTAMP,
execution_duration INTEGER
);
COMMENT ON TABLE plan_case IS '计划与用例关联表,同时存储执行结果';
COMMENT ON COLUMN plan_case.id IS '主键ID';
COMMENT ON COLUMN plan_case.plan_id IS '计划ID';
COMMENT ON COLUMN plan_case.case_id IS '用例ID';
COMMENT ON COLUMN plan_case.assignee_id IS '执行人ID';
COMMENT ON COLUMN plan_case.round_no IS '执行轮次';
COMMENT ON COLUMN plan_case.status IS '执行状态0未开始 1通过 2失败 3阻塞';
COMMENT ON COLUMN plan_case.actual_result IS '实际执行结果';
COMMENT ON COLUMN plan_case.defect_links IS '缺陷链接数组';
COMMENT ON COLUMN plan_case.attachments IS '附件数组';
COMMENT ON COLUMN plan_case.executed_time IS '执行时间';
COMMENT ON COLUMN plan_case.execution_duration IS '执行耗时,单位秒';
CREATE UNIQUE INDEX IF NOT EXISTS uk_plan_case_round ON plan_case(plan_id, case_id, round_no);
CREATE INDEX IF NOT EXISTS idx_plan_case_plan ON plan_case(plan_id);
CREATE INDEX IF NOT EXISTS idx_plan_case_assignee ON plan_case(assignee_id);
CREATE INDEX IF NOT EXISTS idx_plan_case_status ON plan_case(status);
-- -------------------------
-- 10. 测试轮次表
-- -------------------------
CREATE TABLE IF NOT EXISTS test_round (
id BIGSERIAL PRIMARY KEY,
plan_id BIGINT NOT NULL REFERENCES test_plan(id) ON DELETE CASCADE,
round_no INTEGER NOT NULL,
name VARCHAR(64),
start_date DATE,
end_date DATE
);
COMMENT ON TABLE test_round IS '测试轮次表';
COMMENT ON COLUMN test_round.id IS '主键ID';
COMMENT ON COLUMN test_round.plan_id IS '计划ID';
COMMENT ON COLUMN test_round.round_no IS '轮次编号';
COMMENT ON COLUMN test_round.name IS '轮次名称';
COMMENT ON COLUMN test_round.start_date IS '开始日期';
COMMENT ON COLUMN test_round.end_date IS '结束日期';
CREATE UNIQUE INDEX IF NOT EXISTS uk_test_round_plan_round_no ON test_round(plan_id, round_no);
CREATE INDEX IF NOT EXISTS idx_test_round_plan_id ON test_round(plan_id);
-- =========================================================
-- 四、报告相关
-- =========================================================
-- -------------------------
-- 11. 报告表
-- -------------------------
CREATE TABLE IF NOT EXISTS report (
id BIGSERIAL PRIMARY KEY,
plan_id BIGINT NOT NULL REFERENCES test_plan(id) ON DELETE CASCADE,
name VARCHAR(128) NOT NULL,
report_type SMALLINT DEFAULT 1,
summary JSONB,
content TEXT,
file_url VARCHAR(512),
generated_by BIGINT,
generated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE report IS '测试报告表';
COMMENT ON COLUMN report.id IS '主键ID';
COMMENT ON COLUMN report.plan_id IS '计划ID';
COMMENT ON COLUMN report.name IS '报告名称';
COMMENT ON COLUMN report.report_type IS '报告类型1实时报告 2归档报告';
COMMENT ON COLUMN report.summary IS '报告统计摘要JSON格式';
COMMENT ON COLUMN report.content IS '报告HTML内容';
COMMENT ON COLUMN report.file_url IS '导出文件地址';
COMMENT ON COLUMN report.generated_by IS '生成人';
COMMENT ON COLUMN report.generated_time IS '生成时间';
CREATE INDEX IF NOT EXISTS idx_report_plan_id ON report(plan_id);
CREATE INDEX IF NOT EXISTS idx_report_generated_time ON report(generated_time);
-- -------------------------
-- 12. 缺陷同步表
-- -------------------------
CREATE TABLE IF NOT EXISTS defect_sync (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL REFERENCES project(id),
external_id VARCHAR(64) NOT NULL,
external_system VARCHAR(32),
plan_case_id BIGINT REFERENCES plan_case(id),
status VARCHAR(32),
last_sync_time TIMESTAMP
);
COMMENT ON TABLE defect_sync IS '缺陷同步表,用于记录外部缺陷系统关联关系';
COMMENT ON COLUMN defect_sync.id IS '主键ID';
COMMENT ON COLUMN defect_sync.project_id IS '项目ID';
COMMENT ON COLUMN defect_sync.external_id IS '外部缺陷ID如 JIRA-123';
COMMENT ON COLUMN defect_sync.external_system IS '外部系统,如 jira/tapd/zentao';
COMMENT ON COLUMN defect_sync.plan_case_id IS '计划用例执行ID';
COMMENT ON COLUMN defect_sync.status IS '外部缺陷状态';
COMMENT ON COLUMN defect_sync.last_sync_time IS '最后同步时间';
CREATE INDEX IF NOT EXISTS idx_defect_sync_project_id ON defect_sync(project_id);
CREATE INDEX IF NOT EXISTS idx_defect_sync_plan_case_id ON defect_sync(plan_case_id);
CREATE INDEX IF NOT EXISTS idx_defect_sync_external_id ON defect_sync(external_id);
-- =========================================================
-- 五、造数相关
-- =========================================================
-- -------------------------
-- 13. 造数器表
-- -------------------------
CREATE TABLE IF NOT EXISTS data_builder (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
name VARCHAR(128) NOT NULL,
description TEXT,
builder_type SMALLINT DEFAULT 1,
definition JSONB NOT NULL,
input_schema JSONB,
output_example JSONB,
created_by BIGINT,
is_delete INTEGER DEFAULT 0,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE data_builder IS '数据构造器表';
COMMENT ON COLUMN data_builder.id IS '主键ID';
COMMENT ON COLUMN data_builder.project_id IS '项目ID';
COMMENT ON COLUMN data_builder.name IS '造数器名称';
COMMENT ON COLUMN data_builder.description IS '造数器描述';
COMMENT ON COLUMN data_builder.builder_type IS '造数器类型1流程编排 2SQL 3脚本';
COMMENT ON COLUMN data_builder.definition IS '造数逻辑定义JSON格式';
COMMENT ON COLUMN data_builder.input_schema IS '输入参数结构定义';
COMMENT ON COLUMN data_builder.output_example IS '输出示例';
COMMENT ON COLUMN data_builder.created_by IS '创建人';
COMMENT ON COLUMN data_builder.is_delete IS '逻辑删除标记0未删除 1已删除';
COMMENT ON COLUMN data_builder.created_time IS '创建时间';
COMMENT ON COLUMN data_builder.updated_time IS '更新时间';
CREATE INDEX IF NOT EXISTS idx_data_builder_project_id ON data_builder(project_id);
CREATE INDEX IF NOT EXISTS idx_data_builder_is_delete ON data_builder(is_delete);
-- -------------------------
-- 14. 造数任务表
-- -------------------------
CREATE TABLE IF NOT EXISTS data_task (
id BIGSERIAL PRIMARY KEY,
builder_id BIGINT NOT NULL REFERENCES data_builder(id),
project_id BIGINT NOT NULL,
params JSONB,
status SMALLINT DEFAULT 0,
result_data JSONB,
error_message TEXT,
created_by BIGINT,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
completed_time TIMESTAMP
);
COMMENT ON TABLE data_task IS '数据生成任务表';
COMMENT ON COLUMN data_task.id IS '主键ID';
COMMENT ON COLUMN data_task.builder_id IS '造数器ID';
COMMENT ON COLUMN data_task.project_id IS '项目ID';
COMMENT ON COLUMN data_task.params IS '任务入参JSON格式';
COMMENT ON COLUMN data_task.status IS '任务状态0等待 1执行中 2成功 3失败';
COMMENT ON COLUMN data_task.result_data IS '生成结果数据';
COMMENT ON COLUMN data_task.error_message IS '错误信息';
COMMENT ON COLUMN data_task.created_by IS '创建人';
COMMENT ON COLUMN data_task.created_time IS '创建时间';
COMMENT ON COLUMN data_task.completed_time IS '完成时间';
CREATE INDEX IF NOT EXISTS idx_task_status ON data_task(status);
CREATE INDEX IF NOT EXISTS idx_data_task_builder_id ON data_task(builder_id);
CREATE INDEX IF NOT EXISTS idx_data_task_project_id ON data_task(project_id);
-- =========================================================
-- 六、更新时间自动维护触发器
-- 说明:
-- PostgreSQL 需要借助触发器维护 updated_time
-- =========================================================
CREATE OR REPLACE FUNCTION update_updated_time_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_time = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS trg_project_updated_time ON project;
CREATE TRIGGER trg_project_updated_time
BEFORE UPDATE ON project
FOR EACH ROW
EXECUTE FUNCTION update_updated_time_column();
DROP TRIGGER IF EXISTS trg_product_updated_time ON product;
CREATE TRIGGER trg_product_updated_time
BEFORE UPDATE ON product
FOR EACH ROW
EXECUTE FUNCTION update_updated_time_column();
DROP TRIGGER IF EXISTS trg_test_case_updated_time ON test_case;
CREATE TRIGGER trg_test_case_updated_time
BEFORE UPDATE ON test_case
FOR EACH ROW
EXECUTE FUNCTION update_updated_time_column();
DROP TRIGGER IF EXISTS trg_test_plan_updated_time ON test_plan;
CREATE TRIGGER trg_test_plan_updated_time
BEFORE UPDATE ON test_plan
FOR EACH ROW
EXECUTE FUNCTION update_updated_time_column();
DROP TRIGGER IF EXISTS trg_data_builder_updated_time ON data_builder;
CREATE TRIGGER trg_data_builder_updated_time
BEFORE UPDATE ON data_builder
FOR EACH ROW
EXECUTE FUNCTION update_updated_time_column();