purescript-selda icon indicating copy to clipboard operation
purescript-selda copied to clipboard

Enable value-level codecs to be used instead of type-level codecs

Open JordanMartinez opened this issue 3 years ago • 3 comments

Right now, the WriteForeign/ReadForeign and ToSQLValue/FromSQLValue type classes are used to encode/decode values to/from the underlying database.

Could this type-level codec requirement be lessened, so that value-level codecs could be used instead (e.g. purescript-codec-argonaut)?

If so, I believe the Table type could take a record as an additional argument whose fields' values correspond to the codecs to use when encoding/decoding values for a given column.

JordanMartinez avatar Jun 08 '21 19:06 JordanMartinez

Yes, that would be nice to have, but it's a bit problematic right now as it requires quite a bit of work. I don't have enough time to implement it myself, but I can at least describe how I see it, and maybe someone would want to tackle it on their own.

  • Table is backend agnostic so I wouldn't mix it with codecs
  • These type classes are only used for executing queries (functions like query, insert, etc.) and not building queries (where Table is concerned - this sort of restricts the number of files that need changes) with the only exception being lit (also litPG and litSQLite3)
  • it's already easy to make a version of lit that uses codecs instead of type class overloading, the following function is the backbone of both litPG and litSQLite3
litUnsafeFromForeign ∷ ∀ col s a. Coerce col ⇒ Foreign → col s a
litUnsafeFromForeign = unsafeFromCol <<< Col <<< EForeign

The purpose of codecs or these ad-hoc type classes is to encode/decode records that represent rows in a database. One record is encoded as Array Foreign.

The first problem to tackle is to expose low-level, unsafe API in the postgresql-client as the currently exported functions require these ad-hoc type classes anyway. It would allow us to pass/get Foreign values to/from pg-client and handle conversion on our own. For now we could work around that as ToSQLRow accepts Array Foreign (it's already utilized to simplify the implementation of insert_ but not insert nor query because of the following problem), but the problem is that FromSQLRow does not have an instance for Array Foreign so we have to operate on a typed representation which requires more type-level programming. We need either of the following solutions:

The second step would be to implement a generic query operation that uses codecs

  • I'd start by simplifying genericQueryPG: https://github.com/Kamirus/purescript-selda/blob/e2c56b046d88d4c9462a1a7eb177c05de502ce47/src/Selda/PG/Class.purs#L170-L183 by using the unsafeQuery in the pgQuery to return foreigns instead of typed rows thus dropping ColsToPGHandler entirely (look at genericQuerySQLite3 for inspiration)

In case anyone would want to implement feel free to ask about any details or questions

Kamirus avatar Jun 09 '21 09:06 Kamirus

Rather than export unsafeQuery directly as is, couldn't there be other versions of the other functions there (e.g. query) that drop the ToSQLRow and FromSQLRow type class constraints?

JordanMartinez avatar Jun 09 '21 13:06 JordanMartinez

I think so, yes

Kamirus avatar Jun 10 '21 08:06 Kamirus