Open clord opened 7 years ago
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
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.
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 theEither
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?