-
Notifications
You must be signed in to change notification settings - Fork 11.1k
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
PHP DateTime Milliseconds rounding error can cause SqlServer DB Error #22407
Comments
Your test does not seem to involve any database at all. Is the mention of SQL Server important at all? |
You're correct, the test doesn't involve a database - mainly because you can prove the incorrect rounding without hitting the database. However if you use MySQL and write '2017-11-14 08:23:19.1000' into a datetime column then it accepts the value - so although incorrect due to bad rounding, it causes no errors. Using SqlServer a datetime column cannot accept more than milliseconds and so the database write fails - because this code is used by the updated_at column there's potential for any model update with timestamps to fail on SqlServer (1 in 2000 chance). |
Can you update the issue to focus on what you're actually reporting? If a database is irrelevant, then there's no need to mention SQL Server. It looks like you have a problem with a Model method, but it's unclear which. The numbers you're showing has the milliseconds cut off, they're not rounded.
|
I also see that you've filed a bug in the carbon repository. Is this a Carbon bug? If so, wouldn't it be enough for them to fix it? Okay, okay, I almost feel bad for saying that. They don't fix stuff. briannesbitt/Carbon#863 |
I just discovered that it's actually a PHP DateTime bug. Need to close that Carbon issue... I'll update the issue to hopefully explain it better |
I'm not sure I quite understand what your issue here is. Is "08:23:19.1000" with a "H:i:s.v" format even a valid date? I'd expect it to truncate to .100 as milliseconds are only three digits. If it were ".u", I'd expect it to zerofill to .100000, so I don't see how or why you'd get .999 out of it by "truncating". |
Updated issue description - hopefully explains it better. The problem is caused by a bug in PHP DateTime format - but it's due to a change in the Laravel framework that it's been exposed to users to SQL Server. |
Can confirm this is also causing issues here. The bug seems to be solved in PHP 7.2 (https://bugs.php.net/bug.php?id=74753), but current implementation will give database errors in versions lower than that. |
I have the same issue. I discovered it when I was running some seeders as they insert hundreds of rows that affect the |
Is there an alternative solution for this issue? I solved the issue by creating a BaseModel. All models should extend this BaseModel. |
According to this, there should be PHP 7.2 drivers for Ubuntu 16.04. trait DateFormat
{
/**
* Get the format for database stored dates.
*
* @return string
*/
public function getDateFormat()
{
return str_replace(['.v', '.u'], '.000', parent::getDateFormat());
}
} As far as I can see, a proper solution would require additional logic for these code pieces: |
Closing this, as it seems to be a bug in PHP7.2. You can use the solution posted by @FrittenKeeZ as a backport workaround if needed. |
Description:
A bug in PHP (below 7.2) causes microsecond values >=999500 to be rounded to '1000' when formatted using 'v'.
Since 3af1858 set the SQL Server date format to 'Y-m-d H:i:s.v' this means that these values are put into a date string in as '2017-11-14 08:23:19.1000' which causes an illegal write exception in SQL Server as a datetime column can only support milliseconds.
This affects the Builder->addUpdatedAtColumn method which is called on all models with timestamps as this method defers to Model->freshTimestampString() which uses getDateFormat() to output the date as a string - meaning every model will occasionally try and set updated_at to an illegal value and causes the SQL write to fail.
Steps To Reproduce:
By changing the below test from framework/tests/Database/DatabaseEloquentIntegrationTest.php you can cause it to fail - proving the string rounding/truncating bug.
The text was updated successfully, but these errors were encountered: