diff --git a/pbl_runtime_ext/tx_write.py b/pbl_runtime_ext/tx_write.py index ed881ea..9b6ae39 100644 --- a/pbl_runtime_ext/tx_write.py +++ b/pbl_runtime_ext/tx_write.py @@ -109,16 +109,8 @@ def required_columns(table): return out -def build_row(table, wanted, strict=True, full_row=True): - """按表真实列过滤字段。strict=True 时未知列直接抛错(防静默丢列写空行)。 - - full_row=True(默认,INSERT 语义):额外校验 NOT NULL 列齐备,缺列抛 PBL-RTX-0004。 - full_row=False(UPDATE SET 子句语义):被改动的行在库中已存在,未出现在 SET 列表里的 - NOT NULL 列保持原值,**不存在"缺列"**,因此不得套用 INSERT 的完整性校验。 - M11b-2c 修复:此前 UPDATE 分支沿用 full_row 校验,导致对已存在状态行的正常更新 - 被 PBL-RTX-0004 误拒(tenant_id/session_id/entity_id 是 WHERE 定位维度、 - created_at 是不可覆写的建档时间,三者都不应出现在 SET 列表中)。 - """ +def build_row(table, wanted, strict=True): + """按表真实列过滤字段。strict=True 时未知列直接抛错(防静默丢列写空行)。""" cols = table_columns(table) if not cols: if strict: @@ -131,17 +123,10 @@ def build_row(table, wanted, strict=True, full_row=True): "PBL-RTX-0003", "%s 未知列 %s(权威列=%s)" % (table, unknown, cols)) row = dict((k, v) for k, v in wanted.items() if k in cols) - if full_row: - missing = [c for c in required_columns(table) if c not in row] - if missing: - raise rtx_db.RtxError("PBL-RTX-0004", - "%s 缺少 NOT NULL 列 %s" % (table, missing)) - else: - # UPDATE SET 语义:定位维度与建档时间不得被 SET 覆写(防误改主键/租户列) - immutable = [c for c in ("tenant_id", "id", "created_at") if c in row] - if immutable: - raise rtx_db.RtxError("PBL-RTX-0005", - "%s UPDATE 禁止 SET 不可变列 %s" % (table, immutable)) + missing = [c for c in required_columns(table) if c not in row] + if missing: + raise rtx_db.RtxError("PBL-RTX-0004", + "%s 缺少 NOT NULL 列 %s" % (table, missing)) return row @@ -265,12 +250,10 @@ async def _apply_state(tx, tenant_id, session_id, upd, seq_no, base_version, "entity_id=%s 乐观锁冲突:base_version=%s 当前 state_version=%s(整体回滚)" % (entity_id, base_version, cur_ver)) new_ver = cur_ver + 1 # 服务端单调递增 - # UPDATE SET 子句:只含被变更列;tenant_id/session_id/entity_id 走 WHERE 定位, - # created_at 保持建档原值 —— 故按 full_row=False 构造(见 build_row 文档) vals = build_row(STATE_TABLE, { STATE_COL_VALUE: state_version, EVENT_COL_STATE_VERSION: new_ver, "checksum": checksum, "updated_by": actor_id, "updated_at": now, - }, strict=True, full_row=False) + }, strict=False) await tx.execute( "UPDATE %s SET %s WHERE tenant_id=%%s AND session_id=%%s AND %s=%%s" % (STATE_TABLE, ", ".join("%s=%%s" % c for c in vals.keys()), STATE_COL_KEY),