The HDBC documentation states:
fetchAllRows :: Statement -> IO [[SqlValue]]Source
Lazily fetch all rows from an executed Statement.
You can think of this as hGetContents applied to a database result set.
The result of this is a lazy list, and each new row will be read, lazily, from the database as the list is processed.
When you have exhausted the list, the Statement will be finished.
Please note that the careless use of this function can lead to some unpleasant behavior. In particular, if you have not consumed the entire list, then attempt to finish or re-execute the statement, and then attempt to consume more elements from the list, the result will almost certainly not be what you want.
But then, similar caveats apply with hGetContents.
Bottom line: this is a very convenient abstraction; use it wisely.
Use fetchAllRows' if you need something that is strict, without all these caveats.
Then, I wonder, to which level does the laziness extend?
Say, I can have
conn <- connectSqlite3 databaseFilePath rows <- quickQuery conn ("SELECT * FROM foo")  mapM_ bar $ take n rows disconnect conn
Will it actually only fetch
n rows? Like, from the database point of view, will it be equivalent of
SELECT * FROM foo LIMIT (n)? Because fetching all rows at the level of database driver and then
n of them seems to be silly and kind of defeats the purpose.
If it's lazy up to the database itself, how's it implemented? Is it using cursors?
I know there're several drivers for HDBC alone. I'm asking only about principle of implementation.