Does DB.getTables use 'unsafeInterleaveIO'?<br><br>I would think that if an unsafe operation was *not* used, DB.disconnect could *not* execute before DB.getTables has returned every row.<br><br>Either way, by the <a href="http://en.wikipedia.org/wiki/Principle_of_least_astonishment">
Principle of Least Surprise</a>, I think Tim's original code ought to be made to work, despite not leveraging laziness. <br><br>If you are going to tuck away an unsafeInterleaveIO, it seems reasonable that an explicit disconnect should force those deferred operations to be evaluated. Maybe the same should be done for hGetContents/hClose too?
<br><br>Thanks,<br>Greg<br><br><br><div><span class="gmail_quote">On 10/9/06, <b class="gmail_sendername">John Goerzen</b> <<a href="mailto:email@example.com">firstname.lastname@example.org</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
On Mon, Oct 09, 2006 at 04:01:02PM -0600, Tim Smith wrote:<br>> main =<br>> do<br>> dbh <- connectODBC "DSN=test"<br>> res <- DB.getTables dbh<br>> -- print (show ((concat . intersperse ", ") res))
<br>> DB.disconnect dbh<br>> print (show ((concat . intersperse ", ") res))<br>><br>> Am I just expecting the wrong thing from Haskell? Is there a<br><br>Yes. Remember the Haskell mantra: no computation is performed before
<br>its result is demanded. Since you are not demanding the list of tables<br>until the print statement, the code to get the list of tables is not<br>executed until then.<br><br>Actually, follow that logic through. Think about when the connection to
<br>the database is established. If I understand things properly, it won't<br>happen until your call to disconnect, since nothing demands the handle<br>until then. Note that this is normally not the case, since the first
<br>use of it will demand that the connection happens.<br><br>I think the easiest way around this is to add this line after the call<br>to getTables:<br><br>return $ seq res res<br><br>though you may also be able to say:<br>
<br>evaluate res<br><br>(provided you have imported Control.Exception)<br><br>But the very best way is to simply not disconnect until after you've<br>printed.<br><br>> technical reason why HDBC can't synchronize the IO so that everything
<br>> is resolved before the disconnect? Or is this a bug in HDBC?<br><br>It's a Feature of Haskell, not a bug.<br><br>This is the same feature that lets you process infinite lists, treat<br>multi-GB files as strings, and, in fact, treat multi-GB SQL result sets
<br>as simple lists. Haskell only loads each line of the file, or row of<br>result, into RAM when it is demanded. (Note that some databases are<br>less lazy than Haskell in this respect, so this only works if your<br>database API can return partial results!)
<br><br>I have tried to put warnings into the HDBC docs where I think people are<br>particularly likely to run afoul of this -- quickQuery springs to mind.<br><br>Note that the API docs for getTables, at<br><a href="http://darcs.complete.org/hdbc/doc/Database-HDBC.html#v%3AgetTables">
http://darcs.complete.org/hdbc/doc/Database-HDBC.html#v%3AgetTables</a><br>mention that the data is returned in the same manner as fetchAllRows.<br>Click on the link to fetchAllRows and you see:<br><br> Lazily fetch all rows from an executed Statement.
<br><br> You can think of this as hGetContents applied to a database result set.<br><br> The result of this is a lazy list, and each new row will be read,<br> lazily, from the database as the list is processed.<br><br>
When you have exhausted the list, the Statement will be finished.<br><br> Please note that the careless use of this function can lead to some<br> unpleasant behavior. In particular, if you have not consumed the entire
<br> list, then attempt to finish or re-execute the statement, and then<br> attempt to consume more elements from the list, the result will almost<br> certainly not be what you want.<br><br> But then, similar caveats apply with hGetContents.
<br><br> Bottom line: this is a very convenient abstraction; use it wisely.<br><br>-- John<br><br>_______________________________________________<br>Haskell-Cafe mailing list<br><a href="mailto:Haskell-Cafe@haskell.org">