postgresql-simple icon indicating copy to clipboard operation
postgresql-simple copied to clipboard

instance (FromField a) => FromRow (Map (Either Int Text) a)

Open clord opened this issue 8 years ago • 2 comments

One of our APIs queries one of a number of tables, and return all of the columns (I know, wonderful design)

In a runtime language one might marshal the row to a dictionary and then write it out as JSON.

postgresql-simple does not seem to have easy support for capturing a row as a Map, so I'm experimentally working on writing instance (FromField a) => FromRow (Map (Either Int Text) a), where the Either is the name or the column number depending on if the name is available for that column. I don't think my hacky version is production-ready yet but such an instance might be useful to have in the library itself. Or perhaps I'm missing a more obvious way to do this?

clord avatar Apr 14 '17 17:04 clord

Sorry for not responding earlier.

I've taken this approach on a few of my projects. e.g.

data AttrName a = AttrName !ByteString a

instance FromField a => FromField (AttrName a) where
   fromField f mv = AttrName (fromJust (name f)) <$> fromField f mv

Uhh, I'm not sure when name returns Nothing. I don't think it does, because the postgres convention is that unnamed columns are provided the name column1, column2, etc, but don't quote me on that. The underlying libpq fname C call would return Nothing when called on null pointer, but that shouldn't ever happen in haskell-land with vanilla postgresql-simple. So the fact that name returns Maybe ByteString instead of ByteString might just be a minor thing I overlooked in the API.

In any case, it would probably be more efficient to handle column1 etc as an integer; whether or not that makes a tangible difference in your use case, I don't know. It would definitely be more efficient to split the columns into two maps, though, one for ints, the other for descriptive names

lpsmith avatar Apr 21 '17 16:04 lpsmith

As for the possibility of including AttrName in postgresql-simple, or take it one step further with instance (FromField a) => FromRow (Map Text a), I don't know, I haven't thought about it much. Maybe? I suppose it all depends on how often people are writing this sort of thing, and to what extent we can accommodate most similar use cases with one approach.

lpsmith avatar Apr 21 '17 16:04 lpsmith