lpsmith / postgresql-simple

Mid-level client library for accessing PostgreSQL from Haskell
Other
206 stars 71 forks source link

ToField Action typing #265

Open defanor opened 6 years ago

defanor commented 6 years ago

Sometimes PostgreSQL gets confused about types if there's no explicit typing; I've noticed it with a non-empty array (PGArray) of enum elements, which gets recognized as text[] instead of user_role[] in my case. Setting types in queries explicitly is a bit cumbersome in some cases, and it would be handy if postgresql-simple facilitated it. For instance, the following works, but it uses Plain for something other than its intended purpose as it's described in the documentation (that is, it's a hack):

instance ToField Role where
  toField r = Many [Escape $ BS8.pack $ show r, Plain ":: user_role"]

Maybe something like a Typed Action String action constructor should be introduced, or the Plain description should be adjusted. It may be out of scope of postgresql-simple, but seems like ToField is the appropriate place for adding type information.

lpsmith commented 5 years ago

Yes, I absolutely do want to implement something like this. However, my circumstances have changed, and I haven't been working on postgresql-simple for some time now; though I do plan on returning to this project someday. I really should bear down and get a simpler new release finished in the meantime, though.

Personally, I don't think this instance is that terrible of a hack. And, something along these lines may be necessary for implementing protocol-level parameters, as every such parameter is tagged with a type oid. I haven't investigated all the issues surrounding this, but I would imagine that picking the right type oid is far more critical for binary protocol-level parameters than it is for textual protocol-level parameters.

lpsmith commented 5 years ago

Oh, I would point out you can already create something like this more generically (and more robustly):

data TypeAnnotation a = TypeAnnotation a QualifiedIdentifier

instance ToField a => ToField (TypeAnnotation a) where
  toField (TypeAnnotation x t) = Many [toField x, Plain " :: ", toField t]

I'm not sure if I've ever actually used this definition, though I know it's occurred to me several times. That doesn't really address the issue of how to come up with the QualifiedIdentifier automatically, though, which is sometimes nice or perhaps even necessary.