fix: drop the conflict target so partitioned tables can accept writes
PG requires a partitioned table's unique constraints to include the partition key, so issue #12's RANGE partitioning on created_at forces the primary key to (call_id, created_at). The old `ON CONFLICT (call_id) DO NOTHING` then matches no constraint and PG rejects every row with there is no unique or exclusion constraint matching the ON CONFLICT specification which the recorder swallows as a per-row warning: telemetry would go silently dark under a partitioned deployment. The target-free form is valid on both table shapes and is literally equivalent on a plain table (the primary key is its only unique constraint). SQLite's `INSERT OR IGNORE` already carries no target and is untouched. Integration coverage on the real PG instance, both inside self-created temp schemas: a plain table still keeps one row per call_id, and a table partitioned by created_at now accepts writes and reads them back. The second case was red before this change with the error above.
This commit is contained in:
@@ -155,6 +155,13 @@ def insert_sql(backend: str, columns: Sequence[str]) -> str:
|
||||
字符串拼进 SQL(占位符只保护值,保护不了列名)。sqlite 用 `?`、postgres 用 `$n`,
|
||||
两端的重复键处理都不绑定具体约束名(`INSERT OR IGNORE` / `ON CONFLICT`)。
|
||||
|
||||
**PG 的 `ON CONFLICT` 一律不带冲突目标,不得"顺手"补回 `(call_id)`**: PG 要求
|
||||
分区表的唯一约束必须包含分区键,按 `created_at` 分区(issue #12 的保留期方案)后
|
||||
主键变成 `(call_id, created_at)`,带目标的语句匹配不到任何约束,PG 直接拒收
|
||||
("there is no unique or exclusion constraint matching the ON CONFLICT
|
||||
specification"),而遥测写失败只逐行 warning——分区部署下会全线静默丢数据。
|
||||
无目标版本在两种表形态上都合法,普通表上语义逐字等价(表上只有主键一个唯一约束)。
|
||||
|
||||
Args:
|
||||
backend: `"sqlite"` 或 `"postgres"`。
|
||||
columns: 要写入的列,顺序即占位符顺序(调用方须按同序取值)。
|
||||
@@ -176,7 +183,7 @@ def insert_sql(backend: str, columns: Sequence[str]) -> str:
|
||||
placeholders = ", ".join("?" for _ in selected)
|
||||
return f"INSERT OR IGNORE INTO {TABLE} ({names}) VALUES ({placeholders})"
|
||||
placeholders = ", ".join(f"${i + 1}" for i in range(len(selected)))
|
||||
return f"INSERT INTO {TABLE} ({names}) VALUES ({placeholders}) ON CONFLICT (call_id) DO NOTHING"
|
||||
return f"INSERT INTO {TABLE} ({names}) VALUES ({placeholders}) ON CONFLICT DO NOTHING"
|
||||
|
||||
|
||||
def telemetry_schema_sql(backend: str) -> str:
|
||||
|
||||
Reference in New Issue
Block a user