Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

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

オープン 初心者向け
#50 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
88/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
ios, sqlite, typescript
領域
database, mobile

調査の方向性

src/sqlite/sqlite.ios.ts の getRaw() から始め、結果セットの処理を selectRaw() およびヘルパーの getResultsAsObject()/getResultsAsArray() と比較します。空の結果を含め、get() と getArray() の両方について iOS で再現することを確認し、最初の行が返され、行がない場合は TypeError なしで null が返されることを確認します。

索引モデルが 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 ファイルなし
  • プルリクエストのテンプレートあり
  • コントリビューションガイドなし

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

nativescript-community/sqlite のほかの issue

nativescript-community/sqlite の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。