跳到主要内容

assertQueryCacheRowContract()

function assertQueryCacheRowContract(
entityName,
rows,
metadata
): void;

Defined in: packages/rxdb-adapter-sqlite-core/src/query-cache-row-contract.ts:266

落地前校验远端行的列集,不合契约就 fail-fast。

Parameters​

ParameterTypeDescription
entityNamestringQueryCacheEngine 传入的逻辑实体名,原样进错误消息
rowsreadonly object[]待落地的远端行
metadata| Readonly<EntityMetadataType> | undefined实体元数据;查不到时跳过前两条判据(本地表的非空列集无从算起),第 3 条照旧

Returns​

void

Remarks​

三条判据,成因不同、修法也不同,因此消息里分开写:

  1. 缺非空列 —— 本地表建成 NOT NULL 且无 SQL 默认值,写下去必被 SQLite 拒。 今天的表现是一条 NOT NULL constraint failed: public$recipes.createdAt:表名是加了 命名空间前缀的本地表名、列名在远端的 schema 里根本不存在、调用栈落在适配器内部 而不是那次 find() —— 三重误导,读者第一反应是「本地表建错了」。
  2. 非空列带了键但值是空 —— { createdAt: null } 会带着键通过第 1 条,再被数据库以 同一条 NOT NULL 报错拒掉。远端那一列可空、或 select 带了没命中的 join 时, select('*') 返回的正是这个形状,不是理论形态。修法与第 1 条不同(要去查远端为什么 这一列是 null),因此单列一栏。
  3. 批内异构 —— upsertMany 的列清单取自 data[0],后续行按同一批键取值。缺哪个键 就绑 undefined,落到 SQLite 上是 NULL:可空列会被静默清空,连报错都没有。

判在落地前,而不是捕获 SQLite 错误再翻译:翻译要匹配驱动的字符串,而 wa-sqlite / sqlite-wasm / node:sqlite 的措辞各不相同,那是一张要跟着驱动版本一起维护的 正则表。按元数据算出「必须有哪些列」再比对,与驱动无关。

也不给缺列补本地默认值:补出来的 createdAt 是本机拉取的时刻而非记录创建的时刻, 不同设备拉同一行会得到不同的值,且这个污染要到跨设备对比时才暴露。

Throws​

存在不满足契约的行