-
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
[WIP] [5.6] Temporal columns improvements #22004
[WIP] [5.6] Temporal columns improvements #22004
Conversation
Would be nice to have MySQL 5.5 support as a separate driver. |
@deleugpn Yeah, we're discussing this sort of things on laravel/ideas#870 - there's some good ideas there. 👍 |
Can you explain the benefits provided by this PR? |
@paulofreitas can you please try to make your PRs as small as possible, it's extremely hard to understand the PR if it has this amount of line changes. For example here you're changing lots of docblocks, you can do that in a separate PR that has the purpose of "Enhancing docblocks", that way we see only logic changes in the PR, and docblock changes in another. |
f609de6
to
4b527f0
Compare
@taylorotwell Summarizing: All drivers
SQL Server
@themsaid I pushed the commits without squashing to ease reviewing, it's a lot easier to see the commits changes separately. I've summed up the changes above. But I'll do my best to make future PRs much smaller. 👍 Edit note: I've made some simplifications to this PR after your comments. Both PR code and description got reduced/improved. :) |
f0d8c3f
to
c9790dd
Compare
f475cdc
to
c45f4c2
Compare
These are the things that are huge breaking changes. Every soft-deletable model and datetime column gets a new data type. Do we agree that our dev databases should match the production database? If so, how should the dev database be migrated if running the migrations in 5.6 doesn't create a database like they did when they were executed in production (which was running 5.5 at the time)? |
Sorry for making a broad answer here, but I think I should explain the issue in detail.
Actually I was fooled by my own tests: There are more things changing here and they're both breaking changes and bug fixes - that's why I changed my mind and retargeted the PR base branch to 5.6. We should promise that 5.5 won't break in a point release, but we shouldn't promise that a new major version won't affect existing code - this way we'll never be fixing broken things and/or improving existing behavior. It should be noted that we're not following SemVer and this is allowed by the current versioning policy: https://laravel.com/docs/5.5/releases#versioning-scheme Okay, come on. I've reverted Did you see Because they aren't matching expectations. You create a temporal column without declaring any precision and they get stored with a default database precision for the column (7 fractional seconds for Now look the issue #21870 reported recently. It shows us that the The point here is that people shouldn't be expecting any fractional seconds in those columns once all other schema grammars behaves differently and uniformly. We store time/date-time/timestamps columns without declaring any precision and we get timestamps with fractional seconds. Let me show you an experiment I did with SQL Server 2016 using Amazon RDS: Migration
Model
Seeder
Route
Currently if I change There's a conflict of interest here: either you provide support for SQL Server 2005 or you fix all the inconsistencies uniformly. This raises the discussion of providing alternate drivers for legacy database engines we started at laravel/ideas#870. People using SQL Server 2008+ would expect Laravel to behave exactly as shown here: http://sqlfiddle.com/#!6/a22af/1 If the idea of providing separated legacy drivers aren't desirable, maybe we could at least provide a Blueprint option (like I believe that to this PR be complete we should be using |
In the context of migrations; why cannot we make such a promise? I accept that there are code changes in other parts of the framework, and there are usually documented with "if you did this before, do this now" to get the same behavior. Why cannot we do the same here? And if we still can keep the old behavior, why do we need to change existing methods when we can just introduce new methods for the new behavior?
I do not think that this behavior is broken. You did not specify a permission, but let the default decide. So you get the default. The default varies on different platforms, but that is now your problem since you accepted the default. The linked issue (#21870) does mention the actual cause, that this is some shenanigans that is caused by the sqlsrv pdo driver. It's not totally unheard of. microsoft/msphpsql#284 I accept that |
8b9713a
to
892426b
Compare
Okay, I'll admit defeat and give up this discussion. I just found out that 5.5 basically broke every temporal column already with their default of |
If you are fixing an unexpected behavior, the promise could be broken when you bump the major version. Actually #21936 didn't changed anything - currently the schema grammars do not honor any given precision. This PR, on other hand, changes that in the way it was intended in #21936. Look for example that #18847 was added to Laravel 5.5.0 (it got partially reverted/fixed) and changed the existing behavior - it was an improvement, so it's desirable. Earlier Laravel 5.0.0 also changed a lot in 0c0a717 to improve the framework. We can't restrict people from using new features in newer major versions because someone coming from a previous major version does not want to have any changes when upgrading - the only difference you have by following SemVer is that a change like that would require Laravel 5.6 to be versioned Laravel 6. Even following SemVer you're allowed to break things like that if you're improving the software behavior. 👍 Let me give you another example: currently we could've full support for
This is kinda counterintuitive IMO. This way you're simply bloating your API. 😐
That's a good reason to have a decent default that don't confuse people IMO. After all you won't be documenting every single difference a database have to another in a framework pretending to simplify your daily coding. 😄 Please do note that I'm just proposing a complete behavior fix to actually don't have to change this anymore in the future. 👍 |
38b7ff6
to
21d94ab
Compare
21d94ab
to
3c4b33b
Compare
I literally have no idea what is even happening in this PR. |
@taylorotwell I'll make it easy to review by splitting each feature addition/change being proposed into separate PRs. 👍 |
From PR #22000 (broken after rebasing with PR closed)
This was originally targeting 5.5, then I've changed to 5.6. If intended I can rebase this to revert some unwanted change. There was some ongoing discussion on PR #22000 and laravel/ideas#870. 👍
Once again my contribution ended up big and I had to split it with 4 commits to ease the review - it's a lot easier to see the changes separately. I also prepared an extensive summary of changes to help reviewing. 😃
This PR description was a lot simplified after created to ease tracking its changes. Here's a summary of what it changes.
Part 1: Ensure unsupported temporal columns reuse supported ones
Basic code cleanup and consistency improvement. No tests changes yet.
Changes to code - items marked with
*
changes the existing behavior:Illuminate\Database\Schema\Grammars\MySqlGrammar
typeTimeTz()
totypeTime()
Illuminate\Database\Schema\Grammars\PostgresGrammar
typeDateTime()
totypeTimestamp()
*typeDateTimeTz()
totypeTimestampTz()
*Illuminate\Database\Schema\Grammars\SQLiteGrammar
typeTimestamp()
implementation totypeDateTime()
and aliastypeTimestamp()
totypeDateTime()
*typeDateTimeTz()
totypeDateTime()
*typeTimeTz()
totypeTime()
typeTimestampTz()
totypeDateTimeTz()
Illuminate\Database\Schema\Grammars\SqlServerGrammar
typeTimestamp()
implementation totypeDateTime()
and aliastypeTimestamp()
totypeDateTime()
*typeTimestampTz()
implementation totypeDateTimeTz()
and aliastypeTimestampTz()
totypeDateTimeTz()
*typeTimeTz()
totypeTime()
Benefits:
useCurrent()
ondateTime()
anddateTimeTz()
columns (this is improved later)Part 2: Ensure temporal columns handle precision correctly
Improves temporal columns precision handling with full SQL standard compliance. Adds 8 new tests and 76 assertions.
Changes to code - items marked with
*
changes the existing behavior:Illuminate\DatabaseQuery\Grammars\SqlServerGrammar
getDateFormat()
to useY-m-d H:i:s.u
format instead (if may break the application if you use theuseCurrent()
modifier in a columns using theDATETIME
column type)Illuminate\Database\Schema\Blueprint
$precision
argument to the missingtimeTz()
methodIlluminate\Database\Schema\Grammars\MySqlGrammar
Illuminate\Database\Schema\Grammars\PostgresGrammar
Illuminate\Database\Schema\Grammars\SqlServerGrammar
typeTime()
andtypeTimeTz()
to correctly handle the given column precision *Changes to tests:
Illuminate\Tests\Database\DatabaseMySqlSchemaGrammarTest
Illuminate\Tests\Database\DatabasePostgresSchemaGrammarTest
Illuminate\Tests\Database\DatabaseSQLiteSchemaGrammarTest
Illuminate\Tests\Database\DatabaseSqlServerSchemaGrammarTest
testSoftDeletes()
andtestSoftDeletesTz()
testsBenefits:
TIME
,DATETIME
andTIMESTAMP
columnsDATETIME
)Part 3: Ensure all temporal columns handle useCurrent() as supported
Improves all temporal columns to handle the
useCurrent()
column modifier as supported by the database driver in use. Adds 28 new tests and 56 assertions, drops 3 existing tests and 12 assertions.Changes to code:
Illuminate\Database\Schema\Grammars\Grammar
setDefaultTimeFunction()
protected methodIlluminate\Database\Schema\Grammars\MySqlGrammar
Illuminate\Database\Schema\Grammars\PostgresGrammar
Illuminate\Database\Schema\Grammars\SQLiteGrammar
Illuminate\Database\Schema\Grammars\SqlServerGrammar
setTemporalDefault()
methoduseCurrent
handlingWhy I have changed this to use a new method? Because it simplifies things and also ensures the SQL grammars always generate
DEFAULT
expressions afterNULL
/NOT NULL
expressions. All current drivers supportDEFAULT
expressions in either position but theirCREATE TABLE
documentation syntax always placeDEFAULT
expressions afterNOT
/NOT NULL
expressions - thus we can say it's less risky to break if for any reason they change this behavior.Changes to tests:
Illuminate\Tests\Database\DatabaseSchemaBlueprintTest
testDefaultCurrentTimestamp()
method in favor of new grammar-specific testsIlluminate\Tests\Database\DatabaseMySqlSchemaGrammarTest
testAddingTimestampWithDefault()
andtestAddingTimestampTzWithDefault()
methods in favor of new grammar-specific testsIlluminate\Tests\Database\DatabaseMySqlSchemaGrammarTest
Illuminate\Tests\Database\DatabasePostgresSchemaGrammarTest
Illuminate\Tests\Database\DatabaseSQLiteSchemaGrammarTest
Illuminate\Tests\Database\DatabaseSqlServerSchemaGrammarTest
useCurrent()
to all temporal columnsBenefits:
useCurrent()
column modifier on supported temporal columnsPart 4: Improve temporal columns docblocks
Misc docblocks improvements to temporal columns. We're done. 😅
Benefits:
If I didn't miss anything, it's all good. Tests are passing. 👍