feat(plugin): PATCH 部分更新端点 — jsonb_set 字段合并
This commit is contained in:
@@ -266,6 +266,44 @@ impl DynamicTableManager {
|
||||
(sql, values)
|
||||
}
|
||||
|
||||
/// 构建 PATCH SQL — 只更新 data 中提供的字段,未提供的保持不变
|
||||
/// 使用 jsonb_set 逐层合并,实现部分更新
|
||||
pub fn build_patch_sql(
|
||||
table_name: &str,
|
||||
id: Uuid,
|
||||
tenant_id: Uuid,
|
||||
user_id: Uuid,
|
||||
partial_data: serde_json::Value,
|
||||
version: i32,
|
||||
) -> (String, Vec<Value>) {
|
||||
let mut set_expr = "data".to_string();
|
||||
if let Some(obj) = partial_data.as_object() {
|
||||
for key in obj.keys() {
|
||||
let clean_key = sanitize_identifier(key);
|
||||
set_expr = format!(
|
||||
"jsonb_set({}, '{{{}}}', $1::jsonb->'{}', true)",
|
||||
set_expr, clean_key, clean_key
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let sql = format!(
|
||||
"UPDATE \"{}\" \
|
||||
SET data = {}, updated_at = NOW(), updated_by = $2, version = version + 1 \
|
||||
WHERE id = $3 AND tenant_id = $4 AND version = $5 AND deleted_at IS NULL \
|
||||
RETURNING id, data, created_at, updated_at, version",
|
||||
table_name, set_expr
|
||||
);
|
||||
let values = vec![
|
||||
serde_json::to_string(&partial_data).unwrap_or_default().into(),
|
||||
user_id.into(),
|
||||
id.into(),
|
||||
tenant_id.into(),
|
||||
version.into(),
|
||||
];
|
||||
(sql, values)
|
||||
}
|
||||
|
||||
/// 构建 DELETE SQL(软删除)
|
||||
pub fn build_delete_sql(
|
||||
table_name: &str,
|
||||
@@ -871,6 +909,25 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ===== build_patch_sql 测试 =====
|
||||
|
||||
#[test]
|
||||
fn test_build_patch_sql_merges_fields() {
|
||||
let (sql, values) = DynamicTableManager::build_patch_sql(
|
||||
"plugin_test_customer",
|
||||
Uuid::parse_str("00000000-0000-0000-0000-000000000099").unwrap(),
|
||||
Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(),
|
||||
Uuid::parse_str("00000000-0000-0000-0000-000000000050").unwrap(),
|
||||
serde_json::json!({"level": "vip", "status": "active"}),
|
||||
3,
|
||||
);
|
||||
assert!(sql.contains("jsonb_set"), "PATCH 应使用 jsonb_set 合并");
|
||||
assert!(sql.contains("version = version + 1"), "PATCH 应更新版本号");
|
||||
assert!(sql.contains("WHERE id = $3"), "应有 id 条件");
|
||||
assert!(sql.contains("version = $5"), "应有乐观锁");
|
||||
assert_eq!(values.len(), 5, "应有 5 个参数");
|
||||
}
|
||||
|
||||
// ===== build_filtered_count_sql 测试 =====
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user