lpsmith / postgresql-simple

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

Named rather than positional row parser #43

Open ocharles opened 12 years ago

ocharles commented 12 years ago

For projects with multiple queries mapping to the same types, having to get the columns in perfect order is not manageable. It'd be much better if I could do field "id" and field "name" and not care about the ordering.

lpsmith commented 11 years ago

Hmm, we actually did discuss this issue, though there are no comments here. Was this discussion on IRC? I might have to go back through my logs.

lpsmith commented 11 years ago

Yeah, we discussed this on IRC on Oct 10; the main concerns were some of the finer details of how this should work, for example:

If a column name is not found, should this return Nothing or should it throw an error via the Ok mechanism?

Should we use fnumber, which has extra behavior we don't understand?

How should this interact with existing functionality? Would it start searching at the current column or at the first column of the result? Could we make this work with joins reasonably well, which would mean we would need to stop searching at some column in addition to start searching at the current column.

ocharles commented 11 years ago

If a column name is not found, should this return Nothing or should it throw an error via the Ok mechanism?

It may be best to do whatever field is currently doing, so we have consistent behaviour between the two parsers.

Should we use fnumber, which has extra behavior we don't understand?

Not quite following this, but this seems to be an implementation detail so this doesn't entirely matter for the API, does it?

How should this interact with existing functionality? Would it start searching at the current column or at the first column of the result?

What is the definition of 'current column'? Does selecting a field by name change what the current column is? If so, you would still be bound by positional ordering, and the whole point of this is to not be affected by positional ordering. If the position can be conditionally changed then maybe this would be ok, but I'm not sure how you'd determine either when to change it, or by how much. If anything were to do it, I guess :. would be the only place I'd expect it (as that is the 'composition' from a join).

lpsmith commented 11 years ago

PQfnumber attempts to normalize the column name by converting it to lower case, unless it's surrounded by double quotes. It may have additional behaviors as well, though. So this would impact the API, not just be an implementation detail.

And I think it would be nice to have a coherent story for how this would compose with the functionality that's already there. By 'current column' I mean the column number that's maintained inside the RowParser monad, which is used to determine which column an instance of the field action refers to.

And we could pretty easily have :. style composition as is, e.g.

fromRow = Record <$> fieldByName "foo" <*> fieldByName "bar"

xs :: [(Int, String) :. Record] <- DB.query ...

simply by starting the search from the current column, but converting to Record :. (Int, String) is another issue, because we don't have any way to determine how many fields a given FromRow consumes. (And indeed, we can't do that even in principle, without restricting the FromRow interface a bit.)

saurabhnanda commented 7 years ago

I am facing the same issue. I'm wondering why RowParser was designed the way it currently is. Is there an underlying implementation constraint? Why would it not be possible to have something, which conceptually looks like the following:

NewRowParser a = [(Field, Maybe ByteString)] -> Parser a

This would allow users to write positional parsers as well as named/key-value-pair parsers.

lpsmith commented 7 years ago

That's (roughly) what was there before; the newer interface as proposed by Ozgun Ataman turned out to be way more convenient. Note there really is nothing stopping you from doing this without modifying postgresql-simple, probably even via the public interface, but it's not a use case that's convenient yet.

cocreature commented 6 years ago

Hey, just stumbled upon this issue. I actually wrote a lib a while back to support this including automatically deriving decoders based on the names of record fields. Maybe it’s helpful for someone.