iOS: `get()` and `getArray()` always throw on iOS: the result set is read before `next()`
还没有人认领这个 Issue。
评估
- 难度
- 2/5
- 预计耗时
- 1-3 小时
- 新手友好度
- 88/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- ios, sqlite, typescript
调研方向
从 src/sqlite/sqlite.ios.ts 中的 getRaw() 开始,然后将其结果集处理方式与 selectRaw() 以及 getResultsAsObject()/getResultsAsArray() 辅助函数进行比较。验证 get() 和 getArray() 在 iOS 上的复现情况,包括空结果,并确认返回第一行,而没有行时返回 null 且不会出现 TypeError。
由索引模型根据 Issue 内容生成。
描述
Environment
@nativescript-community/sqlite |
3.5.9 (latest) |
@nativescript/core |
9.1.2 |
@nativescript/ios |
9.1.0 |
| NativeScript CLI | 9.1.1 |
| Xcode | 26.3 |
| Device | iPhone 16 Pro simulator, iOS 18.6 |
Android (@nativescript/android 9.1.1) is unaffected - the same code path works there.
What happens
Every call to db.get() or db.getArray() rejects, no matter what the query is or whether it matches any row:
NSqlite Error: TypeError: Cannot read properties of null (reading 'enumerateKeysAndObjectsUsingBlock')
at throwError (node_modules/@nativescript-community/sqlite/sqlite.common.js:72)
Minimal reproduction
import { openOrCreate } from '@nativescript-community/sqlite';
import { knownFolders, path } from '@nativescript/core';
const db = openOrCreate(path.join(knownFolders.documents().path, 'repro.sqlite'));
await db.execute('CREATE TABLE IF NOT EXISTS t (a INTEGER)');
await db.execute('INSERT INTO t (a) VALUES (1)');
await db.select('SELECT a FROM t'); // [{ a: 1 }]
await db.get('SELECT a FROM t'); // throws
Cause
getRaw() in src/sqlite/sqlite.ios.ts hands the fresh FMResultSet straight to getResultsAsObject() / getResultsAsArray() (links below are to the v3.5.9 tag):
and those read resultDictionary right away:
FMDB's resultDictionary describes the row the result set currently sits on, and a result set that has never been stepped sits on no row, so it returns nil - hence the TypeError on null. selectRaw() in the same file gets this right, which is why select() works and get() does not:
Suggested fix
Step onto the first row, and report "no row" rather than an empty object:
function getRaw(db: SQLiteDatabase, query: string, params: SqliteParams, asObject: boolean, options?: SqliteRequestOptions): SqliteRow | SqliteParam[] {
const s = db.db.executeQueryWithArgumentsInArray(query, paramsToStringArray(params));
if (!s) {
throw db.db.lastError();
}
if (!s.next()) {
s.close();
return null;
}
const transformBlobs = options?.transformBlobs ?? db.transformBlobs;
const row = asObject ? getResultsAsObject(s, transformBlobs) : getResultsAsArray(s, transformBlobs);
s.close();
return row;
}
get() and getArray() already coerce a falsy result to null, so the signature does not change.
Workaround
Read single rows through select() and take the first element:
const rows = await db.select(query, params);
const row = rows[0] || null;
PR
I'm happy to open a pull request with the fix above (getRaw() in src/sqlite/sqlite.ios.ts)
- 主要语言
- TypeScript
- 星标
- 26
- 派生
- 4
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 没有贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
nativescript-community/sqlite 的其他 Issue
-
v6未关闭
难度 4/5 3-5 天 新手友好度 25/100
查看 nativescript-community/sqlite 的全部 Issue
相似的 Issue
-
难度 1/5 1 小时以内 新手友好度 78/100
lichess-org/api#678 ·
-
难度 2/5 1-3 小时 新手友好度 84/100
PostHog/posthog.com#20628 ·
维护者通常 1 天内回复
-
bug status:Needs Triage
难度 1/5 1 小时以内 新手友好度 92/100
jupyterlab/jupyterlab#19964 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
agentscope-ai/QwenPaw#8064 · 1 条评论 ·
维护者通常 1 天内回复
-
area: notebooks-jupyter bug theme: new notebook frontend
难度 2/5 1-3 小时 新手友好度 88/100
posit-dev/positron#16347 · 1 条评论 ·
维护者通常 1 天内回复