vapor / fluent-kit

Swift ORM (queries, models, and relations) for NoSQL and SQL databases
MIT License
207 stars 116 forks source link

UUID field backed by String column in Postgres breaks `filter` #427

Open eob opened 3 years ago

eob commented 3 years ago

Describe the bug

I'm using UUIDs for primary keys in my Fluent model representation, like this:

  @ID public var id: UUID?
  @OptionalField(key: .userId) public var userId: UUID?

Backed by string columns in Postgres, like this:

      .field(FieldKey("id"), .string, .identifier(auto: false))
      .field(.userId, .string)

When I attempt to perform a filter operation with QueryBuilder like this:

     .filter(\.$userId == someOtherId)

I get the following error: Optional(server: operator does not exist: text = uuid (op_error))

If filtering records in a SELECT query, this alternative method of invoking filter will avoid the error:

      .filter(.userId, .equal, userId.uuidString.lowercased())

But sometimes this bug is unavoidable: the more compact filter invocation is prevalent inside FluentKit. For example, model.update performs the following filter:

    .filter(\._$id == self.id!)

Is there some workaround that I can use to update my models? I'd prefer to keep the column type text in the database if at all possible.

Thanks for the help! This project is fantastic and I'm really appreciative of all the amazing work on it.

To Reproduce

Steps to reproduce the behavior:

  1. Add package with configuration '...'
  2. Send request with options '...'
  3. See error

Expected behavior

A clear and concise description of what you expected to happen.

Environment

Additional context

Add any other context about the problem here.

0xTim commented 3 years ago

No there is no way around this. Why do you want to keep them as text? Postgres has a native UUID type so that's what Fluent uses. Unfortunately trying to convert that to a string inside Fluent would break too many things.

You might be able to work around this by setting the ID types to Strings instead of UUIDs and converting from UUID to String before you set it in the model