Skip to content

Conversation

@nicktobey
Copy link
Contributor

This PR adds support for Wrapper values, a new type of value that the storage layer can provide to the engine. This is a generalization of the existing JsonWrapper interface, but is not limited to JSON values.

Wrapper types are useful because they can represent a value in storage without needing to fully deserialize that value for the engine. The primary use case is for "out-of-band" storage values, such as large BLOB or TEXT values that aren't stored directly in tables.

The Wrapper interface has the following methods:

Unwrap/UnwrapAny - These methods both deserialize the wrapped value and return it. UnwrapAny returns an interface{}, while Unwrap has a parameterized return type. The implementation is encouraged to cache this value.

IsExactLength - Returns true if the size of the value can be known without deserializing it.

MaxByteLength - The length of the value in bytes. If IsExactLength is true, this is the exact length of the value. Otherwise, it's an upper bound on the length of the value, determined by the schema of the table the value was read from.

Compare - Some Wrapper implementations may be able to compare wrapped values without needing to deserialize them. This method returns a boolean indicating whether or not this "short-circuit" comparison is possible, and an int indicating the result of the comparison.

@nicktobey nicktobey requested a review from zachmu March 17, 2025 05:54
Copy link
Member

@zachmu zachmu left a comment

Choose a reason for hiding this comment

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

LGTM, only real comment is about perf implications, which I assume you'll be measuring in Dolt

return 0, ErrNilOperand.New()
}

if wrapperLeft, isWrapperLeft := left.(sql.AnyWrapper); isWrapperLeft {
Copy link
Member

Choose a reason for hiding this comment

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

Have we profiled this? Type casts to an interface can be relatively expensive, not sure where this is on the hot path but I would expect it to leave a dent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After thinking about it, there's probably not much benefit to this "comparison short-circuit", since (for address types and toast types at least) can't be used to conclude that two values are different, only that they're the same. I'll remove it.

We still need to unwrap values before passing them totypes.TypesEqual. I'll monitor how that affects Dolt performance before I submit.

"context"
)

// This file introduces interfaces for encapsulating values that may be expensive to load or deserialize.
Copy link
Member

Choose a reason for hiding this comment

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

Good docs

@nicktobey nicktobey force-pushed the nicktobey/wrapper branch from 3bf5e3c to 56c0371 Compare April 1, 2025 22:44
@nicktobey nicktobey force-pushed the nicktobey/wrapper branch from fa07a76 to e5862b5 Compare April 2, 2025 21:06
@nicktobey nicktobey merged commit 733cd2c into main Apr 7, 2025
7 of 8 checks passed
@nicktobey nicktobey deleted the nicktobey/wrapper branch April 7, 2025 22:01
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.

4 participants