vapor / fluent-postgres-driver

🐘 PostgreSQL driver for Fluent.
MIT License
149 stars 53 forks source link

Filtering by `PostgreSQLJSONType` field doesn't work #55

Closed MihaelIsaev closed 4 years ago

MihaelIsaev commented 6 years ago

I have Test model with PostgreSQLJSONType field

import FluentPostgreSQL
import Vapor
import Foundation

final class Test: Content{

    struct SomeData: Codable, PostgreSQLJSONType, ReflectionDecodable {
        static func reflectDecoded() throws -> (SomeData, SomeData) {
            return (SomeData(hello: "one"), SomeData(hello: "two"))
        }

        static func reflectDecodedIsLeft(_ item: SomeData) throws -> Bool {
            let leftStr = String(data: try JSONEncoder().encode(try reflectDecoded().0), encoding: .utf8)
            let rightStr = String(data: try JSONEncoder().encode(item), encoding: .utf8)
            return leftStr == rightStr
        }
        var hello: String
    }

    var id: UUID?
    var data: SomeData

    init(data: SomeData) {
        self.data = data
    }
}

extension Test: Model {
    typealias Database = PostgreSQLDatabase

    typealias ID = UUID

    static var idKey: IDKey {
        return \.id
    }
}

extension Test: Parameter { }
extension Test: Migration {}

I added two new records into it

Test(data: Test.SomeData(hello: "world")).save(on: conn)
Test(data: Test.SomeData(hello: "vapor")).save(on: conn)

Then I'm trying to get records from Test model

import Vapor
import Fluent

public func boot(_ app: Application) throws {
    _ = app.requestPooledConnection(to: .psql).flatMap { conn -> EventLoopFuture<Void> in
        return Test.query(on: conn).all().map { tests -> Void in
            print("tests: \(tests)")
        }
    }.map { _ -> Void in
        print("tests done")
    }.catch { error in
        print("tests error: \(error)")
    }
}

and it works, it prints

tests: [App.Test, App.Test]
tests done

but when I'm trying to filter by JSON field

import Vapor
import Fluent

public func boot(_ app: Application) throws {
    _ = app.requestPooledConnection(to: .psql).flatMap { conn -> EventLoopFuture<Void> in
        return try Test.query(on: conn).filter(\Test.data.hello == "world").all().map { tests -> Void in
            print("tests: \(tests)")
        }
    }.map { _ -> Void in
        print("tests done")
    }.catch { error in
        print("tests error: \(error)")
    }
}

it throws an error

tests error: ⚠️ [PostgreSQLDiagnosticResponse.op_error: ERROR: operator does not exist: jsonb = text] [Possible causes: operator does not exist: jsonb = text] [Suggested fixes: No operator matches the given name and argument type(s). You might need to add explicit type casts.]
tanner0101 commented 6 years ago

Fluent doesn't currently support this, but I'm hoping to add support in a future version.