stephencelis / SQLite.swift

A type-safe, Swift-language layer over SQLite3.
MIT License
9.64k stars 1.56k forks source link

Queries not working properly when using Encodable with optional values #989

Closed kamzab95 closed 3 years ago

kamzab95 commented 4 years ago

Build Information

version: 0.12 master xcode: 11.3 iOS: 13.2 integrated with: Carthage

Description

For

class SomeExpression {
    static let name = Expression<String?>("name")
}

class User: Codable {
    var name: String?
}

Query

func foo(name: String)  -> User? { 
    let query = self.table.filter(SomeExpression.name == name)
    ...
}

won't work properly if data were inserted to the database as Encodable. In this case name will never be found. Name, which is String? will be put to database as "\"aabbbbcccc\"". The issue is caused by this additional quotes.

The workaround for this issue is adding the quotes while creating the query :

func foo(name: String)  -> User? { 
    let query = self.table.filter(SomeExpression.name == "\"\(name)\"") // workaround
    ...
}
TenMaKo commented 4 years ago
func encode<T>(_ value: T, forKey key: Key) throws where T: Swift.Encodable {
    if let data = value as? Data {
        self.encoder.setters.append(Expression(key.stringValue) <- data)
    } else if let string = value as? String {
        self.encoder.setters.append(Expression(key.stringValue) <- string)
    } else {
        let encoded = try JSONEncoder().encode(value)
        let string = String(data: encoded, encoding: .utf8)
        self.encoder.setters.append(Expression(key.stringValue) <- string)
    }
}

Make the above modification in Coding.swift to fix this issue.

rahulvyas commented 4 years ago
func encode<T>(_ value: T, forKey key: Key) throws where T: Swift.Encodable {
    if let data = value as? Data {
        self.encoder.setters.append(Expression(key.stringValue) <- data)
    } else if let string = value as? String {
        self.encoder.setters.append(Expression(key.stringValue) <- string)
    } else {
        let encoded = try JSONEncoder().encode(value)
        let string = String(data: encoded, encoding: .utf8)
        self.encoder.setters.append(Expression(key.stringValue) <- string)
    }
}

Make the above modification in Coding.swift to fix this issue.

where is this class Coding.Swift ? can you please provide the class

kamzab95 commented 4 years ago

where is this class Coding.Swift ? can you please provide the class

I think it's SQLite.swift/Sources/SQLite/Typed/Coding.swift line: 131 (class SQLiteEncoder)

rahulvyas commented 4 years ago

where is this class Coding.Swift ? can you please provide the class

I think it's SQLite.swift/Sources/SQLite/Typed/Coding.swift line: 131 (class SQLiteEncoder)

So we need to modify library source code ?

TenMaKo commented 4 years ago

where is this class Coding.Swift ? can you please provide the class

I think it's SQLite.swift/Sources/SQLite/Typed/Coding.swift line: 131 (class SQLiteEncoder)

Yes it is.

So we need to modify library source code ?

If you want to use it with Codable and optional values, yes you do.

You should check this too if you need to work with optional values : Issue 997

nathanfallet commented 3 years ago

Duplicate of #997