Not possible to filter with optional value
rabc opened this issue · 1 comments
rabc commented
Hi,
I have a table where the GeographicPoint2D
property is optional and it is not possible to use filterGeometryDistanceWithin
with this property without force-unwrapping it. I made a unit test to showcase this situation:
func testOptionalLocation() throws {
struct UserGeographicLocation: PostgreSQLModel, Migration {
var id: Int?
var name: String
var location: GeographicPoint2D?
}
let conn = try benchmarker.pool.requestConnection().wait()
conn.logger = DatabaseLogger(database: .psql, handler: PrintLogHandler())
defer { benchmarker.pool.releaseConnection(conn) }
try UserGeographicLocation.prepare(on: conn).wait()
defer { try! UserGeographicLocation.revert(on: conn).wait() }
let point: GeographicPoint2D = GeographicPoint2D(longitude: 1, latitude: 2)
var user = UserGeographicLocation(id: nil, name: "My User", location: point)
user = try user.save(on: conn).wait()
// Crash:
// Fatal error: Unexpectedly found nil while unwrapping an Optional value
// without the `!`, it will not build
let all = try UserGeographicLocation.query(on: conn).filterGeometryDistanceWithin(\UserGeographicLocation.location!, point, 1000).all().wait()
XCTAssertEqual(all.count, 1)
}
I tried to look the code to find a solution, but couldn't find any way to workaround or fix it.
rabc commented
Found a solution: use Database.QueryField
. Here is the test without errors:
func testOptionalLocation() throws {
struct UserGeographicLocation: PostgreSQLModel, Migration {
var id: Int?
var name: String
var location: GeographicPoint2D?
}
let conn = try benchmarker.pool.requestConnection().wait()
conn.logger = DatabaseLogger(database: .psql, handler: PrintLogHandler())
defer { benchmarker.pool.releaseConnection(conn) }
try UserGeographicLocation.prepare(on: conn).wait()
defer { try! UserGeographicLocation.revert(on: conn).wait() }
let point: GeographicPoint2D = GeographicPoint2D(longitude: 1, latitude: 2)
var user = UserGeographicLocation(id: nil, name: "My User", location: point)
user = try user.save(on: conn).wait()
let all = try UserGeographicLocation.query(on: conn).filterGeometryDistanceWithin(.keyPath(\UserGeographicLocation.location),
PostgreSQLDatabase.queryFilterValueGeometry(point),
1000).all().wait()
XCTAssertEqual(all.count, 1)
}