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

Postgres date-time types #2890

Merged
merged 1 commit into from
Oct 30, 2024
Merged

Postgres date-time types #2890

merged 1 commit into from
Oct 30, 2024

Conversation

itowlson
Copy link
Contributor

@itowlson itowlson commented Oct 17, 2024

This is based on @tyler-harpool's work in #2865. I've migrated it to the new v3 world and the new package structure, and implemented it into the Postgres factor.

So far this has not yet been tested (the kindest thing that can be said about it is that it compiles... on my machine). I'm putting the draft PR up so that Rust and Wasm gurus can suggest easier/terser ways of doing things.

@tyler-harpool, I hope you don't feel this is treading on your toes, but some of the migration stuff was a bit tricky and tedious, and I really wanted to get a handle on what implementing an interface upgrade was going to look like. I apologise in advance if I have caused any upset. Also if you have any feedback on the way I've implemented the new types (see the to_sql_parameter function in client.rs) then that would be super useful as I'm not very au fait with the specifics of Postgres types! Thanks!

@itowlson
Copy link
Contributor Author

related: #2870

@tyler-harpool
Copy link

tyler-harpool commented Oct 17, 2024

Happy @itowlson to see you take this on.

Edit: The client stuff was tedious. I was getting close to figuring out, but your legendary skills are the goal for me. Not there yet.

Copy link
Contributor

@kate-goldenring kate-goldenring left a comment

Choose a reason for hiding this comment

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

Just had a few comments to understand how we are handling timezone.

.ok_or_else(|| anyhow!("invalid date y={y}, m={mon}, d={d}"))?;
Ok(Box::new(naive_date))
}
ParameterValue::Time((h, min, s, ns)) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would we support time zone input? It looks like Postgres allows some standard timezone extensions that a user could provide as an optional parameter.

Alternatively, we can document in the WIT that UTC is assumed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Timezones is a good question and I am not sure of the answer. Postgres seemed to have two timestamp types, one with and one without timezones. @tyler-harpool as the first person to pick this up and the person with the strongest interest in Postgres date types, how do you feel about this?

wit/deps/[email protected]/postgres.wit Outdated Show resolved Hide resolved
str(string),
binary(list<u8>),
date(tuple<s32, u8, u8>), // (year, month, day)
time(tuple<u8, u8, u8, u32>), // (hour, minute, second, nanosecond)
Copy link
Contributor

Choose a reason for hiding this comment

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

Did we consider letting users provide strings for date and time?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Strings at the WIT level? No, these specifications follow @tyler-harpool's original PR, and I think mimic Postgres' own concept of what the types contain. I'd be wary of strings at the WIT level because they're so flexible and their semantics so ambiguous, although I know Postgres allows e.g. time('11:22:33') in SQL so maybe it would be fine. In my mind I'd expect adapters so users would pass things like Rust chrono::NaiveDate or JS Date rather than raw WIT fields but maybe I am overthinking it? I am not sure

Copy link
Contributor

Choose a reason for hiding this comment

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

time('11:22:33') this was the precise example i was thinking about that shows how permissive PG is and how it can parse many formats. By adapter do you mean SDKs on top of the WIT? Regardless, I am happy to leave this as is. We can always add a type with a string parameter if there are user requests

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, SDKs or helper functions or whatever. Like Rust's native Postgres driver accepts chrono::NaiveDate for dates, so it would be good to offer something like that.

@@ -59,21 +65,26 @@ impl<C: Client> InstanceState<C> {
}
}

#[async_trait]
impl<C: Send + Sync + Client> v2::Host for InstanceState<C> {}
fn v2_params_to_v3(
Copy link
Contributor

Choose a reason for hiding this comment

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

@itowlson have you tried running a v2 app on this v3 interface as a sanity check?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've run an application using the Rust SDK 3 (which sits over the v2 interfaces) and it worked fine. It wasn't a very comprehensive test though, I fear...

| v2::rdbms_types::ParameterValue::Uint16(_)
| v2::rdbms_types::ParameterValue::Uint32(_)
| v2::rdbms_types::ParameterValue::Uint64(_) => {
return Err(v2::rdbms_types::Error::ValueConversionFailed(
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this a breaking change to v2 apps? Or were we throwing errors for this previously (in 2.0)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, v2 apps also failed, but later, during the "convert rdbms-types type to Postgres type" stage (

ParameterValue::Uint8(_)
). It's possible there's a change to the error text or the way it's reported, but since this was a "type error at runtime," I'm reasonably confident that nobody was relying on the specifics of unsigned type errors - if they had an unsigned type in Postgres code then they ripped the type out rather than handling the error.

If you or other folks feel that's an unreasonable judgment, I can look at other ways to tackle this! But I'm definitely keen to keep unsigned types out of the v3 interface.

Copy link
Contributor

Choose a reason for hiding this comment

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

Failing earlier sounds good to me and i agree that folks relying on a specific error does not seem to outweigh the benefit of removing unsigned types

Copy link
Contributor

@kate-goldenring kate-goldenring left a comment

Choose a reason for hiding this comment

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

Thanks for answering all my questions. LGTM!

@itowlson itowlson merged commit c021968 into fermyon:main Oct 30, 2024
17 checks passed
@vdice vdice mentioned this pull request Nov 4, 2024
9 tasks
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.

3 participants