On 1/12/04 10:47 AM, Tim Bunce wrote: > And this is what I'd like you to be thinking about > (mostly directed at driver authors): > > A. What changes you'd like to see in the DBI API.
This topic came up before, when DateTime was just getting off the ground. DateTime is a lot more mature now, and I still think it's a good idea :) I mentioned earlier that I've written a lot of DBI wrappers, and that the wrappers usually have some per-dbh flag that indicates whether or not I'm in the middle of a transaction. This is the type of thing that should be added to DBI 2 (see earlier thread). Along those lines, all of my DBI wrappers have also had a uniform API for DB-specific date parsing and formatting. My most recent DBI wrapper uses DateTime as the interchange format for dates. Like the transaction flag, this should be part of DBI. Here's my motivation. Once I get a date from a database, I usually want to do something with it: compare it to another date (from the same database, another database, or somewhere else entirely), do date math, etc. This is a pain because the string I get from the database is often db-specific. When comparing it to anything, I have to convert both dates to some common format. To "avoid the trouble", I have seen (and, sadly, written) code that just assumes the date values will string-compare as expected. Bad idea! When I add a date to a database, that date may come from many different sources and be in all kinds of formats. It's a pain to have to maintain code that can parse and format all the different kinds of dates for all the different databases, so I end up just implementing the subset I actually need to use. This doesn't foster code reuse, and in fact, I've done it myself several times already. Bleh. I think this functionality should be added to DBI, specifically to each DBD. The requirements are pretty simple: For each date/time column type supported by a particular database, the DBD should provide a family of functions that can take a string and return a DateTime object, and vice versa. Example: CREATE TABLE foo ( date DATE, # e.g. '2004-01-02' created DATETIME, # e.g. '2004-01-02 12:34:56' modified TIMESTAMP, # e.g. '20040102123456.789123' ... ); ... $sth = $dbh->prepare('SELECT * FROM foo'); $sth->execute; $row = $sth->fetchrow_hashref; # Get DateTime objects from the column values $date = $dbh->parse_date($row->{'date'}); $created = $dbh->parse_datetime($row->{'created'}); $modified = $dbh->parse_timestamp($row->{'modified'}); ... $sth = $dbh->prepare('INSERT INTO foo (date, created, modified) ' . ' VALUES (?, ?, ?)'); $sth->execute($dbh->format_date('20050102'), $dbh->format_datetime($created), $dbh->format_timestamp_keyword('now')); # see below That's the functionality, anyway. The exact API is up for grabs. As far as I've seen, DateTime can handle all the "weird" dates like the infinities, and can support any timezone stuff that the DBs use. DateTime also handles date math, comparisons, and has an extensible formatting/parsing system. The trickiest part is getting the DBD parsing functions to handle the various kinds of keywords supported by databases: 'now', 'today', 'allballs', '-infinity', etc. To that end, it may also be useful to have a family of functions that translates between equivalent keywords. For example: # If the DBD supports the 'allballs' keywords, this is a # pass-through. If not, '00:00:00' may be returned. $kw = $dbh->format_time_keyword('allballs'); The DBD's quote() function would also need to know how to handle the various keywords that may be returned by the parse_*_keyword() functions (e.g. 'now' is quoted, but NOW() isn't) In all cases, if there is something a DBD doesn't know how to do, it should be a fatal error. This proposal doesn't add any overhead to a DBD (except perhaps to quote(), but there could be a separate function for quoting date/time keywords if that is a concern) since all of the formatting and parsing functions must be used explicitly. I think it would go a long way towards making DBI even more database-independent, it'd save a lot of DBI users a lot of time and effort, and it'd encourage better code by making correct comparisons an date math even easier than doing it "the wrong way." Taken to the next level (a la Perl 6 and Larry-think :) DBI 2 could implement all of this as part of a generic DBD-specific column type formatting/parsing system. But I just care about dates right now :) -John