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

Allow custom OID serialization #154

Merged
merged 34 commits into from
Jul 19, 2024
Merged

Allow custom OID serialization #154

merged 34 commits into from
Jul 19, 2024

Conversation

dullbananas
Copy link
Contributor

@dullbananas dullbananas commented Jun 8, 2024

Fixes #103

@dullbananas dullbananas changed the title Add test for OID lookup issue (and maybe fix it) Allow custom OID serialization Jun 10, 2024
@dullbananas dullbananas marked this pull request as ready for review June 10, 2024 05:09
@weiznich
Copy link
Owner

Thanks for working on this. Unfortunately I won't have the capacity to review this soon due to the need to handle some cleanup after the last diesel release and because I'm away for holiday soon. It's on my list to look at this after I'm back in July.

Copy link
Owner

@weiznich weiznich left a comment

Choose a reason for hiding this comment

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

I finally found some time to go over the changes and note some thoughts.

First of all I would like to thank you for working on this and finding this solution. That is really good work.

I have notes some ideas how to side step the more expensive parts of this approach that I think might be worth to try out, even if the introduce more complexity.

src/pg/mod.rs Outdated
/// Allows unambiguously determining:
/// * where OIDs are written in `bind_collector.binds` after being returned by `lookup_type`
/// * determining the maximum hardcoded OID in `bind_collector.metadata`
struct SameOidEveryTime {
Copy link
Owner

Choose a reason for hiding this comment

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

I wonder whether we can add a flag to this type that tracks whether or not we hit a custom type (called the lookup function).
This would allow us to use this knowledge above to skip the second run of the bind collector and the comparison for the common case that we don't have any custom type.

Copy link
Owner

Choose a reason for hiding this comment

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

Another alternative would be to just collect the relevant type names here so that we already have them for later lookups. And we can check if that list is empty before doing the expensive stuff.

The other quick idea that I have is to use something uniquely identifiable per type instead a constant OID. Maybe a truncated hash value of the type name? (For the second variant we can just add a constant, because only the difference in the output is relevant, right?)

src/pg/mod.rs Outdated
/// * where OIDs are written in `bind_collector.binds` after being returned by `lookup_type`
/// * determining the maximum hardcoded OID in `bind_collector.metadata`
struct SameOidEveryTime {
first_byte: u8,
Copy link
Owner

Choose a reason for hiding this comment

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

I likely would just use a 'u32' directly here instead of constructing it everytime in the lookup function.

src/pg/mod.rs Outdated
let collect_bind_result =
query.collect_binds(&mut bind_collector, &mut metadata_lookup, &Pg);

let fake_oid_locations = std::iter::zip(bind_collector_0.binds, bind_collector_1.binds)
Copy link
Owner

Choose a reason for hiding this comment

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

I'm not sure if it might be worth to do that in the future anyway just do allow us to perform the comparison and the replacement in one pass.

src/pg/mod.rs Outdated
@@ -367,10 +366,35 @@ impl AsyncPgConnection {
//
// We apply this workaround to prevent requiring all the diesel
// serialization code to beeing async
let mut metadata_lookup = PgAsyncMetadataLookup::new();
let mut bind_collector_0 = RawBytesBindCollector::<diesel::pg::Pg>::new();
let collect_bind_result_0 = query.collect_binds(
Copy link
Owner

Choose a reason for hiding this comment

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

We want to have some comment here why these steps are necessary and how the approach works from a top level view. Just to make sure that future refactoring won't break it again.

@dullbananas dullbananas marked this pull request as draft July 5, 2024 20:16
* Do not generate a second bind collector if we don't encounter a custom
oid at all
* Do not generate a third bind collector at all, we don't need that
* Skip comparing buffers for types without custom oids as they won't
contain any difference
* Minor cleanup + documentation of the approach
@weiznich weiznich marked this pull request as ready for review July 19, 2024 08:08
@weiznich
Copy link
Owner

I've pushed a bunch of cleanups + optimizations. This should be good to go now.

@weiznich weiznich merged commit a893571 into weiznich:main Jul 19, 2024
38 checks passed
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.

Failed to find a type oid for ENUM_TYPE
2 participants