From b4928eb7e5cebe10dc34efbaecdd98963ca98cad Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Sat, 23 Dec 2023 22:31:21 +0000 Subject: [PATCH] Chore: Mobile: Fixed regression that would prevent the app from running on Android 7 --- .eslintignore | 1 + .gitignore | 1 + packages/lib/models/Resource.ts | 51 +++++++++++++++---- .../services/database/isSqliteSyntaxError.ts | 4 ++ 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 packages/lib/services/database/isSqliteSyntaxError.ts diff --git a/.eslintignore b/.eslintignore index 979e37d35..bb23ded58 100644 --- a/.eslintignore +++ b/.eslintignore @@ -776,6 +776,7 @@ packages/lib/services/commands/propsHaveChanged.js packages/lib/services/commands/stateToWhenClauseContext.js packages/lib/services/contextkey/contextkey.js packages/lib/services/database/addMigrationFile.js +packages/lib/services/database/isSqliteSyntaxError.js packages/lib/services/database/migrations/42.js packages/lib/services/database/migrations/43.js packages/lib/services/database/migrations/44.js diff --git a/.gitignore b/.gitignore index 1dce8c0a8..d716b1062 100644 --- a/.gitignore +++ b/.gitignore @@ -756,6 +756,7 @@ packages/lib/services/commands/propsHaveChanged.js packages/lib/services/commands/stateToWhenClauseContext.js packages/lib/services/contextkey/contextkey.js packages/lib/services/database/addMigrationFile.js +packages/lib/services/database/isSqliteSyntaxError.js packages/lib/services/database/migrations/42.js packages/lib/services/database/migrations/43.js packages/lib/services/database/migrations/44.js diff --git a/packages/lib/models/Resource.ts b/packages/lib/models/Resource.ts index 0aaa9b07a..0baf15618 100644 --- a/packages/lib/models/Resource.ts +++ b/packages/lib/models/Resource.ts @@ -22,6 +22,7 @@ import { htmlentities } from '@joplin/utils/html'; import { RecognizeResultLine } from '../services/ocr/utils/types'; import eventManager, { EventName } from '../eventManager'; import { unique } from '../array'; +import isSqliteSyntaxError from '../services/database/isSqliteSyntaxError'; export default class Resource extends BaseItem { @@ -553,15 +554,47 @@ export default class Resource extends BaseItem { return this.modelSelectAll(`SELECT id, ocr_text FROM resources WHERE id IN ("${ids.join('","')}")`); } - public static allForNormalization(updatedTime: number, id: string, limit = 100, options: LoadOptions = null) { - return this.modelSelectAll(` - SELECT ${this.selectFields(options)} FROM resources - WHERE (updated_time, id) > (?, ?) - AND ocr_text != "" - AND ocr_status = ? - ORDER BY updated_time ASC, id ASC - LIMIT ? - `, [updatedTime, id, ResourceOcrStatus.Done, limit]); + public static async allForNormalization(updatedTime: number, id: string, limit = 100, options: LoadOptions = null) { + const makeQuery = (useRowValue: boolean): SqlQuery => { + const whereSql = useRowValue ? '(updated_time, id) > (?, ?)' : 'updated_time > ?'; + + const params: any[] = [updatedTime]; + if (useRowValue) { + params.push(id); + } + params.push(ResourceOcrStatus.Done); + params.push(limit); + + return { + sql: ` + SELECT ${this.selectFields(options)} FROM resources + WHERE ${whereSql} + AND ocr_text != "" + AND ocr_status = ? + ORDER BY updated_time ASC, id ASC + LIMIT ? + `, + params, + }; + }; + + // We use a row value in this query, and that's not supported on certain + // Android devices (API level <= 24). So if the query fails, we fallback + // to a non-row value query. Although it may be inaccurate in some cases + // it wouldn't be a critical issue (some OCRed resources may not be part + // of the search engine results) and it means we can keep supporting old + // Android devices. + try { + const r = await this.modelSelectAll(makeQuery(true)); + return r; + } catch (error) { + if (isSqliteSyntaxError(error)) { + const r = await this.modelSelectAll(makeQuery(false)); + return r; + } else { + throw error; + } + } } public static async save(o: ResourceEntity, options: SaveOptions = null): Promise { diff --git a/packages/lib/services/database/isSqliteSyntaxError.ts b/packages/lib/services/database/isSqliteSyntaxError.ts new file mode 100644 index 000000000..f997c9316 --- /dev/null +++ b/packages/lib/services/database/isSqliteSyntaxError.ts @@ -0,0 +1,4 @@ +// Syntax errors have a code 0 (no error) so we need to check the message. +export default (sqliteError: any) => { + return sqliteError.message && sqliteError.message.includes('syntax error'); +};