-
Notifications
You must be signed in to change notification settings - Fork 8k
Fix #74243: pdo_dblib option to get milliseconds #2859
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Why not add an option to let people pass in a format string? A general solution seems like it would be better. There's a ticket from others asking for a different kind of tweak. |
This adds a new attribute PDO::DBLIB_ATTR_MILLISECOND that changes the date format to include milliseconds. Date formating is still based on dbdatecrack + printf, but the millisecond value returned by the driver is appended to the list of arguments. The option appends ".%3d" to the printf format, which is now stored with the db handle.
This adds a new attribute PDO::DBLIB_ATTR_MILLISECOND that changes the date format to include milliseconds. The string format now includes milliseconds, if the option is not present the resulting string is truncated to remove them.
Switch to slprintf as we're dealing with fixed length data
Rename test file
This option controls how datetime data is returned. It has multiple purposes: - "raw" = converted by dblib - "" (default) = former behavior = ISO - "millisecond" = same + millisecond - "object" = same + wrapped in DateTime object - anything else = same + DateTime::format(datetime_format)
|
I was aiming for the simpler less intrusive answer here, in my opinion that's enough fo fix most problems (as the string returned is compatible with DateTime, other conversions can be handled in php). But I agree with the ticket you mention, having the underlying driver handle the formatting is also an elegant solution and should be an option. Anyway, for the sake of conversation, I just pushed a patch on the other and of the spectrum: an overkill solution with a "datetime_format" string option that implements several behaviors:
|
|
Before you get too deep into implementing this, let's talk through the spec and make sure we agree on that. I don't like the idea of setting an attribute to either format strings or sentinel values. That kind of design is hard to future-proof, which is very important with libraries that someone will want to update eventually. I'm really wary of letting this extension return DateTime objects. I don't know much about that (pretty pesky) world. I don't want create potentially unreliable code that could take a while to stabilize, would be hard to future-proof. My suggestion would be to add an attribute that lets you set a format string. When unset, the existing behavior would be used. I don't know what control characters should be used. If we imitate the |
|
Thanks for taking the time to look into this. I too don't like the idea of a string attribute and introducting Also the current behavior must be kept and I think it has its uses (it ensures a consistent output format, compatible with So this last commit is a more sensible solution, the attribute is now an integer with 3 possible values, to keep the current behavior and add these 2 new options:
|
bb682e0 to
d9c5afc
Compare
This adds a DBLIB_ATTR_DATETIME_FORMAT attribute to control how datetime data is converted to string. It implements 3 behaviors: - DBLIB_DATETIME_FORMAT_DEFAULT = converted to YYYY-MM-DD hh:mm:ss - DBLIB_DATETIME_FORMAT_MILLISECOND = converted to YYYY-MM-DD hh:mm:ss.sss - DBLIB_DATETIME_FORMAT_CONVERT = converted by dblib
|
@adambaratz can we have a re-read of the latest patch and a thumbs up or down for this please ? |
|
I don't like the idea of having a second format built in ( |
This adds an attribute to convert datetime data using dblib's dbconvert.
|
I see your point in having a second harcoded format, it should either be scraped or replaced with a customizable format. So here's some more "pick and choose" commits with that in mind, now with two different options:
The first option alone should be enough to satisfy most users, but the second is driver independent and doesn't require access to |
5a9e34d to
41124ce
Compare
This adds two attributes to convert datetime data: - DBLIB_DATETIME_FORMAT_CONVERT: converted by dblib - DBLIB_DATETIME_FORMAT_FORMAT: converted by php using strftime
This adds two attributes to convert datetime data: - DBLIB_DATETIME_FORMAT_CONVERT: converted by dblib - DBLIB_DATETIME_FORMAT_FORMAT: converted by php using strftime, with FreeTDS %z strftime hack.
ext/pdo_dblib/dblib_driver.c
Outdated
| H->stringify_uniqueidentifier = 0; | ||
| H->skip_empty_rowsets = 0; | ||
| H->datetime_convert = 0; | ||
| H->datetime_format = zend_string_init("", 0, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default to NULL so you don't do a needless alloc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, datetime_format is now NULL unless an non-zero-length string is passed
ext/pdo_dblib/dblib_stmt.c
Outdated
|
|
||
| static int pdo_dblib_strftime(zval *output, zend_string *format, DBDATEREC *dr) | ||
| { | ||
| /* mashup of php_date.c php_strftime & FreeTDS convert.c tds_strftime */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would you feel about leaning on ext/date/php_date.c:php_format_date instead? It's designed to be accessible across extensions. The format strings are different, but it'd provide the same functionality (it's what powers the date function).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's how I first tried to implement this, but there were a few drawbacks:
- milliseconds are only supported when using the DateTime object interface (like in this early commit)
- it introduces an unneeded back and forth conversion to unix timestamp (need to call
php_mktimebeforephp_format_date)
ext/pdo_dblib/dblib_driver.c
Outdated
| H->stringify_uniqueidentifier = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, 0); | ||
| H->skip_empty_rowsets = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS, 0); | ||
| H->datetime_convert = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_DATETIME_CONVERT, 0); | ||
| H->datetime_format = pdo_attr_strval(driver_options, PDO_DBLIB_ATTR_DATETIME_FORMAT, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use NULL instead of 0 for the default value.
This adds two attributes to convert datetime data: - DBLIB_DATETIME_FORMAT_CONVERT: converted by dblib - DBLIB_DATETIME_FORMAT_FORMAT: converted by php using date(), with "u"/"f" format hack to support micro/milli seconds
|
So here's a more php-y DATETIME_FORMAT implementation, based on I actually preferred this one and have now figured out a decent way of putting it together:
|
Convert to SYBMSDATETIME2 to get timestamp: - works with FreeTDS < 1 - better precision
|
I fixed this last commit:
|
46a772b to
1322cf1
Compare
|
I know I suggested going in this direction, but I'm getting uncomfortable with the amount of (partially copied, pasted, and rearranged) code involved here. It feels like more business logic than should be living in a driver layer. I'm willing to be okay with it if this is the only way to make it work, but... I'm wondering how true that is. The |
|
I agree, DATETIME_CONVERT is enough and the code I came up for DATETIME_FORMAT is too complicated and doesn't add much (basically an option for people without access to locales.conf). Anyway I'm OK with scratching this last part and focusing on DATETIME_CONVERT, I pushed a commit doing that. One last thing though: I'd like to include SQLDATETIME2 in the switch case (like in this commit), to get a consistent behavior for datetime & datetime2 (as of now datetime2 isn't supported and falls back to the default behavior) |
This adds an attribute to convert datetime data using dblib's dbconvert.
|
Comment on behalf of adambaratz at php.net: Committed b72af30. |
|
This change should be all set. Thanks for all your work on it. I'll take a look at merging the |
|
Thanks for working on this, glad this change made it. Just a thought: the allocation for the generic |
|
Where did you get the 63 for the length? The closest thing I could find in the FreeTDS source was types.csv, which had very different values. |
|
I did some tests with a large With a large enough buffer, datetime_convert.phpt would output something like: |
This is an attempt to fix bug #74243, by providing an option to add milliseconds to the date format.
Date formating is still based on dbdatecrack + printf, but the millisecond value returned by the driver is appended to the list of arguments.
The option appends ".%3d" to the printf format. (which is now a variable stored with the db handle)
With the solution we can't specify a custom date format, but it at least provides a way to get all the data and doesn't significantly change the date handling code. The format is still compatible with "new DateTime()".