Skip to content
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

Set precision 6 by default for datetime columns #42297

Merged
merged 1 commit into from Jun 25, 2021

Conversation

robertomiranda
Copy link
Contributor

@robertomiranda robertomiranda commented May 26, 2021

Summary

Set precision 6 by default for datetime columns, this is the standard behaviour for timestamps #34970 it would good to extend this to all datetimes by default. I've seen this really useful in general when implementing functions relying on time comparison, like cursor pagination. Also, this helps when delivering messages to external services and the ordering matters, or when monotonicity is required.

I'm looking for feedback on this PR and eventually, I will add support to the rest of the adapters supporting precision for datetime and the proper updates around tests and docs. So far I've been trying to find the downside of having a microsecond based timestamp over a second based one by default, the only downside that I've found is the fact that it will require more space, however, the disk space these days are quite cheap wdyt?


NATIVE_DATABASE_TYPES.dup.tap do |types|
type[:datetime][:precision] = 6
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a code knit and not at all related to the feature you're trying to work on 😅 , but how about to write this as:

if supports_datetime_with_precision?
  return NATIVE_DATABASE_TYPES.dup.blahblah
end

return NATIVE_DATABASE_TYPES

The returns could be implicit I guess, but I try to avoid unless here if you're planning to add more types.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zzak zzak requested a review from kamipo May 26, 2021 22:41
@zzak
Copy link
Member

zzak commented May 27, 2021

@robertomiranda I'm also seeing a few failures in CI such as:


Failure:
--
  | ActiveRecord::Migration::ChangeSchemaTest#test_change_column_with_timestamp_type [/rails/activerecord/test/cases/migration/change_schema_test.rb:338]:
  | --- expected
  | +++ actual
  | @@ -1 +1 @@
  | -"timestamp without time zone"
  | +"timestamp(6) without time zone"

and a few others mentioned here, could you check them? 🙇

@robertomiranda
Copy link
Contributor Author

and a few others mentioned here, could you check them?

@zzak sure, I'm on it 👍 🙇

@zzak
Copy link
Member

zzak commented May 27, 2021

@robertomiranda Seeing these now, I think they are related:

/usr/local/bundle/bundler/gems/mysql2-ca883e1a359a/lib/mysql2/client.rb:131:in `_query': Invalid default value for 'modified_datetime' (Mysql2::Error)

@ghiculescu
Copy link
Member

@robertomiranda thanks for working on this. I agree with the change, but it needs to go through the migration versioning system so that it is backward compatible with past Rails versions.

If you look at #41084 I added a sort of similar feature so you can probably copy the pattern there. Specifically c4290da and the discussion from #41084 (comment) might be helpful. Happy to help further.

@robertomiranda
Copy link
Contributor Author

@ghiculescu thank you for the reference, I will have a look 👍

@ghiculescu

This comment has been minimized.

@robertomiranda
Copy link
Contributor Author

Those changes are looking good to me. Can you add a changelog entry?

Done in b716f916b9, I do still have pending to fix/update a couple of test cases for Postgres and MySQL though 😅

@zzak
Copy link
Member

zzak commented Jun 3, 2021

@robertomiranda No rush, let us know if you need a review or have any questions! 🙇

@robertomiranda robertomiranda force-pushed the r/default-precision-datime branch 2 times, most recently from ac0734a to d5caad5 Compare June 5, 2021 09:23
@robertomiranda
Copy link
Contributor Author

@zzak @ghiculescu test fixed! ✅

There is one tiny thing around a test case introduced in #41084 which test custom date time on Postgres

 PostgresqlTimestampWithZone.connection.execute("CREATE TYPE custom_time_format AS ENUM ('past', 'present', 'future');")

Basically, the custom type does not support precision you can see the error on this PR #42401. I ended up setting the precision as nil 4762477 .

wdyt?

@@ -411,6 +411,8 @@ def column(name, type, index: nil, **options)
end
end

options[:precision] ||= 6 if type == :datetime && !options.key?(:precision) && @conn.supports_datetime_with_precision?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you make this block form? More than 2 conditions and this line gets very long to read

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 73c30a4e2a3a44ab1467ef7599bbabbb089eb5b9

@zzak
Copy link
Member

zzak commented Jun 7, 2021

@robertomiranda Thanks! Can you rebase and squash please? 🙇

@ghiculescu
Copy link
Member

@zzak @ghiculescu test fixed! ✅

There is one tiny thing around a test case introduced in #41084 which test custom date time on Postgres

 PostgresqlTimestampWithZone.connection.execute("CREATE TYPE custom_time_format AS ENUM ('past', 'present', 'future');")

Basically, the custom type does not support precision you can see the error on this PR #42401. I ended up setting the precision as nil 4762477 .

wdyt?

I think that approach is fine 👍

@robertomiranda
Copy link
Contributor Author

@zzak @ghiculescu 👋 is there anything pending to cover on this PR?

@ghiculescu ghiculescu added the ready PRs ready to merge label Jun 15, 2021
@ghiculescu
Copy link
Member

@robertomiranda it looks good to me, other than the merge conflict. As it's a new feature it will require someone from the core team to merge it. They are reasonably active but also busy people, and there's lots of PRs open! But sit tight, they'll get to it :)

@robertomiranda
Copy link
Contributor Author

robertomiranda commented Jun 15, 2021

@robertomiranda it looks good to me, other than the merge conflict. As it's a new feature it will require someone from the core team to merge it. They are reasonably active but also busy people, and there's lots of PRs open! But sit tight, they'll get to it :)

Awesome, thanks @ghiculescu, just wanted the know if there was something missing 👌

Copy link
Member

@guilleiguaran guilleiguaran left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rebase

@guilleiguaran guilleiguaran self-assigned this Jun 25, 2021
@guilleiguaran guilleiguaran merged commit 5a26648 into rails:main Jun 25, 2021
@robertomiranda robertomiranda deleted the r/default-precision-datime branch June 25, 2021 16:08
@robertomiranda
Copy link
Contributor Author

Thank you all for help on this PR 🙇

@ghiculescu
Copy link
Member

#43909 and #43934 seem related to this. @robertomiranda are you able to take a look?

y0t4 pushed a commit to y0t4/rails that referenced this pull request Jan 14, 2022
By rails#42297, the default value of datetime precision in rails is now 6.
With this change, if the value of datetime precision is 0, it should be
dumped into schema, but it is not.
So I modified it to dump to schema when the value of datetime precision
is 0, and not to dump when the value is 6, which is the default value of
rails.
rafaelfranca added a commit that referenced this pull request Jan 28, 2022
Since #42297, Rails now generates
datetime columns on MySQL with a default precision of 6. This means
that users upgrading to Rails 7.0 from 6.1, when loading the database
schema, would get the new precision value, which would not match the
production schema.

To avoid problems like this in the future,
Rails will now freeze `ActiveRecord::Schema` class to
be the 7.0 implementation, and will allow access to other version
using the same mechanism of `ActiveRecord::Migration`.

The schema dumper will generate the new format which will include the
Rails version and will look like this:

```
ActiveRecord::Schema[7.0].define
```

Related to #43934 and #43909.
rafaelfranca added a commit that referenced this pull request Feb 7, 2022
Since #42297, Rails now generates
datetime columns on MySQL with a default precision of 6. This means
that users upgrading to Rails 7.0 from 6.1, when loading the database
schema, would get the new precision value, which would not match the
production schema.

To avoid problems like this in the future,
Rails will now freeze `ActiveRecord::Schema` class to
be the 7.0 implementation, and will allow access to other version
using the same mechanism of `ActiveRecord::Migration`.

The schema dumper will generate the new format which will include the
Rails version and will look like this:

```
ActiveRecord::Schema[7.0].define
```

Related to #43934 and #43909.
public-rant pushed a commit to opensource-rant/rails that referenced this pull request Feb 17, 2022
By rails#42297, the default value of datetime precision in rails is now 6.
With this change, if the value of datetime precision is 0, it should be
dumped into schema, but it is not.
So I modified it to dump to schema when the value of datetime precision
is 0, and not to dump when the value is 6, which is the default value of
rails.
public-rant pushed a commit to opensource-rant/rails that referenced this pull request Feb 17, 2022
Since rails#42297, Rails now generates
datetime columns on MySQL with a default precision of 6. This means
that users upgrading to Rails 7.0 from 6.1, when loading the database
schema, would get the new precision value, which would not match the
production schema.

To avoid problems like this in the future,
Rails will now freeze `ActiveRecord::Schema` class to
be the 7.0 implementation, and will allow access to other version
using the same mechanism of `ActiveRecord::Migration`.

The schema dumper will generate the new format which will include the
Rails version and will look like this:

```
ActiveRecord::Schema[7.0].define
```

Related to rails#43934 and rails#43909.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
activerecord ready PRs ready to merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants