Skip to content

Commit 614f6e5

Browse files
Fix: Regenerate Pydantic models to support list owners
Co-authored-by: yourton.ma <yourton.ma@gmail.com>
1 parent dce8c4b commit 614f6e5

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed

CRITICAL_REALIZATION.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# 💡 关键发现
2+
3+
## 🎯 真正的问题所在
4+
5+
您说:
6+
> "我只修改了json文件,没有修改datamodel_generation.py"
7+
8+
**这就是问题!**
9+
10+
### 问题分析
11+
12+
1. **您修改了 JSON Schema** (`ownerConfig.json`)
13+
- 添加了对数组的支持
14+
- 使用 `$ref``definitions`
15+
16+
2. **但是 Pydantic 模型没有重新生成!**
17+
- 旧的 Pydantic 模型还是 `Dict[str, str]`(不支持数组)
18+
- 新的 JSON Schema 定义是 `Dict[str, Union[str, List[str]]]`
19+
20+
3. **结果**
21+
- YAML 配置:`database: {"finance_db": ["alice", "bob"]}`
22+
- Pydantic 验证:**把数组转换成了字符串** `"alice"` 或报错
23+
- 所以 ownerConfig.database 里就只有字符串形式的值
24+
25+
### 为什么会转换成 "alice"?
26+
27+
当 Pydantic 模型期望 `str` 但收到 `List[str]` 时:
28+
- 可能取列表的第一个元素
29+
- 或者调用 `str(["alice", "bob"])` 得到字符串表示
30+
- 或者直接报错(但可能被捕获了)
31+
32+
## ✅ 解决方案
33+
34+
### 步骤 1: 重新生成 Pydantic 模型(必须!)
35+
36+
```bash
37+
cd ~/workspaces/OpenMetadata/openmetadata-spec
38+
39+
# 这一步会根据 JSON Schema 重新生成 Pydantic 模型
40+
mvn clean install
41+
```
42+
43+
**这会做什么**
44+
- 读取 `ownerConfig.json`(您修改过的版本)
45+
- 使用 `datamodel-code-generator` 生成 Python 代码
46+
- 生成的模型会支持 `Union[str, List[str]]`
47+
48+
### 步骤 2: 重新安装 ingestion
49+
50+
```bash
51+
cd ~/workspaces/OpenMetadata/ingestion
52+
53+
# 强制重新安装,使用新生成的模型
54+
pip install -e . --force-reinstall --no-deps
55+
```
56+
57+
### 步骤 3: 验证
58+
59+
```bash
60+
# 运行测试
61+
metadata ingest -c ingestion/tests/unit/metadata/ingestion/owner_config_tests/test-03-multiple-users.yaml
62+
63+
# 检查结果
64+
curl -s "http://localhost:8585/api/v1/databaseSchemas/name/postgres-test-03-multiple-users.finance_db.accounting" \
65+
-H "Authorization: Bearer $JWT_TOKEN" | jq '.owners | length'
66+
67+
# 期望:2(而不是1)
68+
```
69+
70+
## 🔍 为什么之前的修改没用?
71+
72+
### 我们修改的代码(`common_db_source.py`):
73+
74+
```python
75+
database_owner_names = [owner.name for owner in database_owner_ref.root]
76+
database_owner = database_owner_names[0] if len(database_owner_names) == 1 else database_owner_names
77+
```
78+
79+
**这段代码是正确的!**
80+
81+
### 但是它依赖于:
82+
83+
```python
84+
database_owner_ref = self.get_database_owner_ref(database_name)
85+
```
86+
87+
这个函数调用:
88+
89+
```python
90+
owner_ref = get_owner_from_config(
91+
metadata=self.metadata,
92+
owner_config=self.source_config.ownerConfig, # ← 这里!
93+
...
94+
)
95+
```
96+
97+
### 关键:`self.source_config.ownerConfig`
98+
99+
这是一个 **Pydantic 模型实例**
100+
101+
如果 Pydantic 模型定义是:
102+
```python
103+
class OwnerConfig(BaseModel):
104+
database: Optional[Union[str, Dict[str, str]]] # ← 旧模型,不支持 List
105+
```
106+
107+
那么当配置是:
108+
```yaml
109+
database:
110+
"finance_db": ["alice", "bob"]
111+
```
112+
113+
Pydantic 验证时会:
114+
- **拒绝这个配置**(ValidationError)
115+
- 或者**转换成字符串**(取第一个元素)
116+
- 导致 `ownerConfig.database` 实际上是 `{"finance_db": "alice"}`
117+
118+
所以后续代码获取到的就只有1个owner!
119+
120+
## 📊 数据流示意图
121+
122+
### 当前状态(错误)
123+
124+
```
125+
YAML配置: ["alice", "bob"]
126+
127+
Pydantic验证(旧模型,不支持List)
128+
129+
转换/丢失: "alice" ← 问题在这里!
130+
131+
ownerConfig.database = {"finance_db": "alice"}
132+
133+
get_owner_from_config 只能拿到1个owner
134+
135+
database_owner_ref.root = [EntityReference(alice)] ← 只有1个
136+
137+
context 存储 "alice"
138+
139+
schema 继承 "alice"
140+
```
141+
142+
### 修复后(正确)
143+
144+
```
145+
YAML配置: ["alice", "bob"]
146+
147+
Pydantic验证(新模型,支持List)✅
148+
149+
保持原样: ["alice", "bob"] ← 正确!
150+
151+
ownerConfig.database = {"finance_db": ["alice", "bob"]}
152+
153+
get_owner_from_config 拿到2个owner
154+
155+
database_owner_ref.root = [EntityReference(alice), EntityReference(bob)] ← 2个
156+
157+
context 存储 ["alice", "bob"]
158+
159+
schema 继承 ["alice", "bob"] ← 2个owner!
160+
```
161+
162+
## 🎯 总结
163+
164+
**问题根源**:Pydantic 模型没有重新生成,配置解析时就丢失了数据。
165+
166+
**解决方法**:运行 `mvn clean install` 重新生成模型。
167+
168+
**我们之前的修改**(`common_db_source.py`, `owner_utils.py`)都是**正确且必要的**,但它们需要配合重新生成的 Pydantic 模型才能工作!

0 commit comments

Comments
 (0)