Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG-Unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
- [LokiJS] When accessing or opening IndexedDB throws synchronously (e.g. `SecurityError` when storage access is denied), the adapter now falls back to an in-memory database like for other IndexedDB open failures (or fails setup with `allowInMemoryFallback: false`), instead of always failing setup
- [Android] Added linker flag for building with 16kB page alignment
- [TS] make catchError visible to typescript
- [Observation] Fixed `canEncodeMatcher()` reporting queries containing `Q.unsafeSqlExpr`,
`Q.unsafeLokiExpr`, or a `Q.on` nested inside `Q.and`/`Q.or` as encodable.
- [LokiJS] Fixed `unsafeResetDatabase()` failing with "another operation is already in progress" when it's called while an autosave is in progress
- [iOS] Fixed compilation on React Native 0.88, which removed `RCTCxxBridge`; JSI is installed through the bridge or the bridgeless proxy alike
- [Android] Generate `BuildConfig` explicitly (AGP 9 no longer does for libraries) and stop applying the unused Kotlin plugin, which collides with AGP 9's built-in Kotlin support
Expand Down
21 changes: 17 additions & 4 deletions src/observation/encodeMatcher/canEncode.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
// @flow

import type { QueryDescription } from '../../QueryDescription'
import type { QueryDescription, Where } from '../../QueryDescription'

export const forbiddenError = `Queries with joins, sortBy, take, skip, lokiTransform can't be encoded into a matcher`
export const forbiddenError = `Queries with joins, sortBy, take, skip, lokiTransform, Q.unsafeSqlExpr, Q.unsafeLokiExpr can't be encoded into a matcher`

const isEncodableWhere = (where: Where): boolean => {
switch (where.type) {
case 'where':
return true
case 'and':
case 'or':
return where.conditions.every(isEncodableWhere)
default:
return false
}
}

export default function canEncodeMatcher(query: QueryDescription): boolean {
const { joinTables, nestedJoinTables, sortBy, take, skip, lokiTransform, sql } = query
const { joinTables, nestedJoinTables, sortBy, take, skip, lokiTransform, sql, where } = query

return (
!joinTables.length &&
Expand All @@ -14,6 +26,7 @@ export default function canEncodeMatcher(query: QueryDescription): boolean {
!take &&
!skip &&
!lokiTransform &&
!sql
!sql &&
where.every(isEncodableWhere)
)
}
8 changes: 5 additions & 3 deletions src/observation/encodeMatcher/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ const unencodableQueries = [
[Q.take(100)],
[Q.unsafeLokiTransform(() => {})],
[Q.unsafeSqlQuery('select * from tasks')],
[Q.unsafeSqlExpr('')],
[Q.unsafeLokiExpr({})],
[Q.or(Q.on('projects', 'team_id', 'abcdef'))],
[Q.or(Q.unsafeSqlExpr(''))],
[Q.or(Q.unsafeLokiExpr({}))],
]

describe('SQLite encodeMatcher', () => {
Expand Down Expand Up @@ -61,9 +66,6 @@ describe('SQLite encodeMatcher', () => {
// console.log(query)
expect(() => makeMatcher(query)).toThrow(`can't be encoded into a matcher`)
})
expect(() => makeMatcher([Q.or(Q.on('projects', 'team_id', 'abcdef'))])).toThrow('Illegal Q.on')
expect(() => makeMatcher([Q.or(Q.unsafeSqlExpr(''))])).toThrow('Illegal')
expect(() => makeMatcher([Q.or(Q.unsafeLokiExpr({}))])).toThrow('Illegal')
})
})

Expand Down
13 changes: 13 additions & 0 deletions src/observation/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,17 @@ describe('common observation tests', () => {
subscribeToQueryWithColumns(mockDb.tasks.query(...complexQuery), ['position'], observer),
)
})
const unencodableQuery = Q.unsafeLokiExpr({ is_completed: true })
it(`updates list before model - test with an unencodable where clause`, async () => {
const mockDb = mockDatabase()
await updatesListBeforeModelTest(mockDb, (observer) =>
subscribeToQuery(mockDb.tasks.query(unencodableQuery), observer),
)
})
it(`updates list before model - test with an unencodable where clause and columns`, async () => {
const mockDb = mockDatabase()
await updatesListBeforeModelTest(mockDb, (observer) =>
subscribeToQueryWithColumns(mockDb.tasks.query(unencodableQuery), ['position'], observer),
)
})
})
Loading