Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

iOS: `get()` and `getArray()` always throw on iOS: the result set is read before `next()`

未关闭 适合新手
#50 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
88/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
ios, sqlite, typescript
领域
database, mobile

调研方向

从 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):

https://github.com/nativescript-community/sqlite/blob/60489226bc6badacf3a45504a55c1ec882099de4/src/sqlite/sqlite.ios.ts#L266-L279

and those read resultDictionary right away:

https://github.com/nativescript-community/sqlite/blob/60489226bc6badacf3a45504a55c1ec882099de4/src/sqlite/sqlite.ios.ts#L114-L131

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:

https://github.com/nativescript-community/sqlite/blob/60489226bc6badacf3a45504a55c1ec882099de4/src/sqlite/sqlite.ios.ts#L350-L359

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 模板
  • 没有贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

nativescript-community/sqlite 的其他 Issue

查看 nativescript-community/sqlite 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。