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

Upgrade to time 0.3 #1455

Merged
merged 2 commits into from
Apr 14, 2022
Merged

Upgrade to time 0.3 #1455

merged 2 commits into from
Apr 14, 2022

Conversation

paolobarbolini
Copy link
Contributor

@paolobarbolini paolobarbolini commented Sep 24, 2021

Continuation of #1444

Still left to do:

Closes #1277

@paolobarbolini
Copy link
Contributor Author

paolobarbolini commented Oct 1, 2021

It doesn't look like macros like it when time is renamed, since they all import it with ::time
https://github.com/time-rs/time/blob/d700977ce9bc34013ee9841e122edbc807f410e4/time-macros/src/datetime.rs#L47

Any ideas?

@abonander
Copy link
Collaborator

Can we get around using the macros?

@paolobarbolini
Copy link
Contributor Author

Can we get around using the macros?

We could but first I'm trying to see if there are other solutions time-rs/time#356 (reply in thread)

@abonander
Copy link
Collaborator

@paolobarbolini sounds like a solution wasn't forthcoming there. I dunno how feasible it is to try to get time to add a crate parameter to its macros, sounds like it might get stuck in bikeshedding.

Can we just inline the output of the macros here? It seems like it should be relatively stable as the code that format_description!() outputs doesn't appear to use any hidden types or fields.

@kyle-mccarthy
Copy link

I am not familiar with this issue and am not sure the circumstances are the same, but is the method used by the postgres-types crate possible? It looks like they also rename the time crate.

@paolobarbolini
Copy link
Contributor Author

@paolobarbolini sounds like a solution wasn't forthcoming there. I dunno how feasible it is to try to get time to add a crate parameter to its macros, sounds like it might get stuck in bikeshedding.

Can we just inline the output of the macros here? It seems like it should be relatively stable as the code that format_description!() outputs doesn't appear to use any hidden types or fields.

I suggested it but they don't seem too convinced about it time-rs/time#356 (reply in thread)

I'll try inlining the macro output.

I am not familiar with this issue and am not sure the circumstances are the same, but is the method used by the postgres-types crate possible? It looks like they also rename the time crate.

That's what we're doing too

@kyle-mccarthy
Copy link

kyle-mccarthy commented Nov 3, 2021

@paolobarbolini sorry, I didn't link to the correct spot. I meant with how they declare time as an extern crate.

Doing something similar, I was able to run cargo check --manifest-path sqlx-core/Cargo.toml --no-default-features --features offline,all-databases,all-types,migrate,runtime-async-std-native-tls without errors.

The specific changes I made can be viewed here: kyle-mccarthy@005d922

@paolobarbolini
Copy link
Contributor Author

@paolobarbolini sorry, I didn't link to the correct spot. I meant with how they declare time as an extern crate.

Doing something similar, I was able to run cargo check --manifest-path sqlx-core/Cargo.toml --no-default-features --features offline,all-databases,all-types,migrate,runtime-async-std-native-tls without errors.

The specific changes I made can be viewed here: kyle-mccarthy@005d922

Interesting, I didn't know extern crate had the power to rename a crate like that.

@paolobarbolini
Copy link
Contributor Author

I cherry-picked your commit @kyle-mccarthy. I got a warning that the #[macro_use] wasn't necessary, so I tried removing it.

@@ -104,3 +104,6 @@ pub mod mssql;
/// sqlx uses ahash for increased performance, at the cost of reduced DoS resistance.
use ahash::AHashMap as HashMap;
//type HashMap<K, V> = std::collections::HashMap<K, V, ahash::RandomState>;

#[cfg(feature = "time-03")]
extern crate time_03 as time;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we make this conditional on feature = "postgres" as well? It should fix those "unused" warnings.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Or nevermind this if you're still working on support for MSSQL/SQLite

Copy link
Contributor Author

@paolobarbolini paolobarbolini Nov 3, 2021

Choose a reason for hiding this comment

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

Honestly I just tested postgres. I haven't looked into mysql and sqlite, I just fixed the compiler warnings 😄. From a quick search it looks like support for time in sqlite hasn't been implemented yet!? https://github.com/launchbadge/sqlx/tree/master/sqlx-core/src/sqlite/types

Copy link
Collaborator

Choose a reason for hiding this comment

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

It definitely looks to be that way, I guess no one's ever asked for it. I guess don't worry about SQLite then?

So yeah, whatever suppresses the warning works for me.

@abonander
Copy link
Collaborator

I am absolutely ecstatic that this just works! This is a backwards-compatible change too, isn't it? So we could release this with 0.5.10 instead of 0.6.0

@abonander
Copy link
Collaborator

@paolobarbolini do you think you'll be able to finish this soon?

@paolobarbolini
Copy link
Contributor Author

@paolobarbolini do you think you'll be able to finish this soon?

Yes, I'll look into it next week.

Copy link
Collaborator

@abonander abonander left a comment

Choose a reason for hiding this comment

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

Couple remaining nits:

  • can we fix the warnings on the extern crate time_03 as time; in sqlx-core/src/lib.rs when it's not being used?
  • it looks like the existing type tests for time 0.2 were repurposed to test the types from time 0.3 which leaves the former with no type tests, can we make sure to cover both?

@paolobarbolini
Copy link
Contributor Author

it looks like the existing type tests for time 0.2 were repurposed to test the types from time 0.3 which leaves the former with no type tests, can we make sure to cover both?

Ah right. I'll look into it

@paolobarbolini
Copy link
Contributor Author

I'm trying to do point 2 but we're again running into the same problem we had before with both time 0.2 and time 0.3 macros importing time as ::time, which doesn't work because we can have only one version imported with the name time.

@paolobarbolini
Copy link
Contributor Author

It seems to me like these macro issues are going to come up again when time 0.4 comes out. Just to get an idea I looked at the downloads for the latest 0.2 1 and 0.3 2 versions and between the two time 0.3 only makes ~30% of the downloads 😞. I kinda wished everybody updated so we didn't have to do this.

Footnotes

  1. https://crates.io/crates/time/0.2.27

  2. https://crates.io/crates/time/0.3.5

@paolobarbolini
Copy link
Contributor Author

Also I just realized the sqlx-macros optional feature suggestion system should be updated to support both versions 😅

@abonander
Copy link
Collaborator

@paolobarbolini should we just bite the bullet and upgrade to time 0.3 wholesale in 0.6? Might push people to upgrade.

@paolobarbolini
Copy link
Contributor Author

@paolobarbolini should we just bite the bullet and upgrade to time 0.3 wholesale in 0.6? Might push people to upgrade.

👍 I removed all of my changes and rebased the original author's changes on top of master

@tyhi
Copy link
Contributor

tyhi commented Jan 10, 2022

It might be worth to update the time version from 0.3.2 to 0.3.5, that would change MSRV 1.48 -> 1.51.

@abonander
Copy link
Collaborator

Officially, we only support the latest stable version of Rust. I try to avoid using language or library features that are too new but MSRV just isn't something we keep track of on this project. Should probably add a disclaimer somewhere visible for that.

@thomaseizinger
Copy link

It might be worth to update the time version from 0.3.2 to 0.3.5, that would change MSRV 1.48 -> 1.51.

This is a lib (hence no Cargo.lock) so unless we pin it with =0.3.2 in the manifest, the upgrade from 0.3.2 to 0.3.5 will transparently happen in the consumer binary.

@happysalada
Copy link

very interested in this!
It would make the move from chrono to time, much simpler.
Another potential addition, would it make sense to add the time feature serde-human-readable by default?
Without this, all the time structs are not serializable and deserializable
here is the reference https://github.com/time-rs/time/blob/main/Cargo.toml#L36
Or perhaps this should be put behind the crate's serde feature flag

@paolobarbolini
Copy link
Contributor Author

Another potential addition, would it make sense to add the time feature serde-human-readable by default? Without this, all the time structs are not serializable and deserializable here is the reference https://github.com/time-rs/time/blob/main/Cargo.toml#L36 Or perhaps this should be put behind the crate's serde feature flag

The time crate docs say Libraries should never enable this feature, as the decision of what format to use should be up to the user

https://docs.rs/time/0.3.7/time/index.html#feature-flags

@abonander
Copy link
Collaborator

Even if we wanted to enable the feature by default, which we don't for the reason @paolobarbolini stated, I have to question time's choice for their human-readable serialization format, which appears to be:

<year>-<month>-<day> <hours>:<minutes>:<seconds>.<seconds-fraction> <offset>

Which is ever so close to being ISO-8601/RFC 3339 compliant but I believe the space separator for the offset breaks it.

@abonander
Copy link
Collaborator

Indeed, it produces dates like

2022-02-16 20:30:08.33839334 +00:00:00

which are rejected by Javascript's Date.parse(), something we use a lot on the frontend. It's perhaps accepted by more permissive parsers like https://dencode.com/en/date/iso8601 which interpreted the above date just fine somehow, but not stricter ones. It's similarly rejected by Dart's DateTime.parse(), which we use in our Flutter-based mobile app projects.

You can enable RFC-3339 serialization, but you have to mark every time::OffsetDateTime field with #[serde(with = "time::serde::rfc3339")], which uses the serde-well-known feature, not the serde-human-readable feature.

The reasoning for the choice is explained here: time-rs/time#248 (comment)

I don't see why RFC 3339 couldn't have been the default since it's generally more useful for most of the places you'd actually use time with the custom extended-range format being enabled via #[serde(with)], but it's a closed matter anyway.

@abonander abonander added this to the 0.6.0 milestone Feb 16, 2022
@happysalada
Copy link

Thanks for the comments and the correct way to serialize with serde (it all makes sense now).
Looking forward to 0.6!

@@ -151,7 +151,7 @@ sha-1 = { version = "0.9.8", default-features = false, optional = true }
sha2 = { version = "0.9.8", default-features = false, optional = true }
sqlformat = "0.1.8"
thiserror = "1.0.30"
time = { version = "0.2.27", optional = true }
time = { version = "0.3.2", features = ["macros", "formatting", "parsing"], optional = true }

Choose a reason for hiding this comment

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

Wouldn't #[serde(with = "time::serde::rfc3339")] (as described in this comment) require the serde-well-known feature flag? Since serializing with RFC3339 format is a very common use case, I guess adding serde-well-known would make sense...

Copy link
Collaborator

Choose a reason for hiding this comment

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

Generally you don't want to enable feature flags you don't strictly need. That would force that feature on for all crates that depend on SQLx.

Choose a reason for hiding this comment

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

Makes sense... but what is then the recommended way to read a timestamp from the database and put it into a DTO in RFC3339 format? Since the version of time that sqlx comes with doesn't support this (due to version and that feature flag), a user of sqlx has to use an intermediate "DatabaseDTO" with sqlx::types::time::OffsetDateTime for fetching from the database (using query_as), just to then convert it manually into an "ActualDTO" with time::OffsetDateTime (I did that with time::OffsetDateTime::from_unix_timestamp(db_dto.created_at.unix_timestamp()), but I'm not sure that's the best way). Only then the aforementioned way to serialize a timestamp using RFC3339 with with actually works. Or am I missing something?

Copy link
Collaborator

Choose a reason for hiding this comment

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

That's only an issue because SQLx is currently using a different version of time than you are. Otherwise sqlx::types::time::OffsetDateTime and time::OffsetDateTime should always refer to the same type.

Choose a reason for hiding this comment

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

time::serde::rfc3339 exists since time v0.3.6, so it's not available in the version proposed in this PR (which means serde-well-known would only make sense when using >= 0.3.6 anyway; before that, there is no such feature flag).

I get that enabling too many features is not a good idea as it would impact lots of users. But what about going with a more recent version of time, i.e., >=0.3.6? That would make it easier for anyone trying to include timestamps in REST API responses :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

time::serde::rfc3339 exists since time v0.3.6, so it's not available in the version proposed in this PR

sqlx depending on 0.3.2 means versions >=0.3.2, <0.4.0 are allowed, so you're free to use features from newer patch versions of the time crate

Copy link
Collaborator

Choose a reason for hiding this comment

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

The version specified here is not restrictive and Cargo will automatically pull in the latest 0.3.x release if it's not in your Cargo.lock already when building your crate.

You should also specify time = { version = "0.3.6", features = ["serde-well-known"] } in your own dependencies to be certain of this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

time dependency out of date
7 participants