Initial commit of akmon project
This commit is contained in:
136
POSTGRESQL_CONSTRAINT_FIX.md
Normal file
136
POSTGRESQL_CONSTRAINT_FIX.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# PostgreSQL 约束修复说明
|
||||
|
||||
## 问题描述
|
||||
|
||||
在原始的 `video_system_database.sql` 中,使用了 PostgreSQL 不支持的 CHECK 约束语法:
|
||||
|
||||
```sql
|
||||
CONSTRAINT chk_play_media_type CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM ak_contents
|
||||
WHERE id = content_id
|
||||
AND content_type IN ('video', 'audio')
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
PostgreSQL 不允许在 CHECK 约束中使用子查询,这会导致部署时报错。
|
||||
|
||||
## 修复方案
|
||||
|
||||
### 1. 移除了有问题的 CHECK 约束
|
||||
|
||||
移除了以下表中的 CHECK 约束:
|
||||
- `ak_video_play_records.chk_play_media_type`
|
||||
- `ak_image_tags.chk_image_tag_type`
|
||||
- `ak_image_view_records.chk_image_view_type`
|
||||
|
||||
### 2. 应用层校验替代方案
|
||||
|
||||
创建了带内容类型校验的 RPC 函数:
|
||||
|
||||
#### 弹幕插入函数
|
||||
```sql
|
||||
SELECT insert_danmu_with_validation(
|
||||
content_id,
|
||||
'弹幕内容',
|
||||
time_position,
|
||||
color,
|
||||
font_size,
|
||||
position_type
|
||||
);
|
||||
```
|
||||
|
||||
#### 图片标签插入函数
|
||||
```sql
|
||||
SELECT insert_image_tag_with_validation(
|
||||
content_id,
|
||||
'标签名称',
|
||||
'user', -- 标签类型
|
||||
confidence -- 置信度(可选)
|
||||
);
|
||||
```
|
||||
|
||||
#### 播放记录函数
|
||||
```sql
|
||||
SELECT record_play_progress_with_validation(
|
||||
content_id,
|
||||
play_position,
|
||||
play_duration,
|
||||
device_type,
|
||||
resolution,
|
||||
quality
|
||||
);
|
||||
```
|
||||
|
||||
## 数据完整性保证
|
||||
|
||||
### 1. 外键约束
|
||||
所有相关表都有适当的外键约束,确保引用完整性。
|
||||
|
||||
### 2. 应用层校验
|
||||
通过 RPC 函数在应用层进行内容类型校验:
|
||||
- 弹幕:仅限 `video` 和 `audio` 内容
|
||||
- 播放记录:仅限 `video` 和 `audio` 内容
|
||||
- 图片标签:仅限 `image` 内容
|
||||
- 图片浏览记录:仅限 `image` 内容
|
||||
|
||||
### 3. 触发器机制
|
||||
统计更新触发器仍然有效,自动维护内容统计数据。
|
||||
|
||||
## 使用建议
|
||||
|
||||
### 前端调用示例
|
||||
|
||||
```typescript
|
||||
// 弹幕插入
|
||||
const { data: danmuId } = await supabase.rpc('insert_danmu_with_validation', {
|
||||
p_content_id: contentId,
|
||||
p_content: danmuText,
|
||||
p_time_position: currentTime,
|
||||
p_color: '#FFFFFF',
|
||||
p_font_size: 16
|
||||
});
|
||||
|
||||
// 图片标签添加
|
||||
const { data: tagId } = await supabase.rpc('insert_image_tag_with_validation', {
|
||||
p_content_id: imageId,
|
||||
p_tag_name: tagName,
|
||||
p_tag_type: 'user'
|
||||
});
|
||||
|
||||
// 播放进度记录
|
||||
const { data: recordId } = await supabase.rpc('record_play_progress_with_validation', {
|
||||
p_content_id: videoId,
|
||||
p_play_position: currentTime,
|
||||
p_play_duration: totalDuration,
|
||||
p_device_type: 'mobile'
|
||||
});
|
||||
```
|
||||
|
||||
### 错误处理
|
||||
|
||||
RPC 函数会抛出明确的错误信息:
|
||||
- `内容不存在`
|
||||
- `只有视频和音频内容支持弹幕功能`
|
||||
- `只有图片内容支持标签功能`
|
||||
- `只有视频和音频内容支持播放记录`
|
||||
|
||||
### 直接插入的风险
|
||||
|
||||
如果绕过 RPC 函数直接插入数据,可能会导致数据不一致:
|
||||
- 图片内容可能被插入弹幕记录
|
||||
- 视频内容可能被插入图片标签
|
||||
|
||||
建议始终使用提供的 RPC 函数进行数据操作。
|
||||
|
||||
## 部署验证
|
||||
|
||||
修复后的数据库可以正常部署到 Supabase 或任何 PostgreSQL 实例,不会出现约束相关的错误。
|
||||
|
||||
## 下一步
|
||||
|
||||
1. 部署更新后的数据库结构
|
||||
2. 在前端代码中使用 RPC 函数替代直接的表插入
|
||||
3. 测试各种内容类型的操作,确保校验正常工作
|
||||
4. 可选:添加更多业务逻辑校验(如敏感词过滤、权限检查等)
|
||||
Reference in New Issue
Block a user