Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
JordanMartinez opened this issue Jun 8, 2021 · 3 comments
Open

Comments

@JordanMartinez
Copy link
Contributor

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.

@Kamirus
Copy link
Owner

Kamirus commented Jun 9, 2021

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:
    instance genericQueryPG
    ( ColsToPGHandler B i tup o
    , GetCols i
    , FromSQLRow tup
    , MonadSeldaPG m
    ) ⇒
    GenericQuery BackendPGClass m i o where
    genericQuery _ q = do
    let
    (Tuple res _) = runFullQuery q
    { strQuery, params } = showPG $ showQuery q
    rows ← pgQuery (PostgreSQL.Query strQuery) params
    pure $ map (colsToPGHandler (Proxy Proxy BackendPGClass) res) rows
    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

@JordanMartinez
Copy link
Contributor Author

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?

@Kamirus
Copy link
Owner

Kamirus commented Jun 10, 2021

I think so, yes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants