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

feat: sqlx sqlite expose de/serialize #3745

Merged

Conversation

mattrighetti
Copy link
Contributor

@mattrighetti mattrighetti commented Feb 16, 2025

This PR exposes two new functions for sqlite (#192):

  • serialize
  • deserialize

I've tried to follow what @abonander suggested #192 (comment)

Related docs

Serialize

serialize_nocopy uses sqlite3_serialize with the flag SQLITE_SERIALIZE_NOCOPY enabled so no new buffer is allocated. It is implemented on LockedHandle so that we're sure the buffer does not outlive the handle lifetime as noted in the sqlite docs:

After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set, the returned buffer content will remain accessible and unchanged until either the next write operation on the connection or when the connection is closed, and applications must not modify the buffer. If the bit had been clear, the returned buffer will not be accessed by SQLite after the call.

I've then implemented the serialize function on SqliteConnection that basically locks the handle and copies the buffer returned by serialize_nocopy into an owned type Vec<u8> that will be returned to the caller.

Deserialize

deserialize requires a bit more work. First of all I've created a wrapper type SqliteOwnedBuf for a buffer allocated with sqlite3_malloc. That buffer is useful in sqlite3_deserialize since it enables us to use the SQLITE_DESERIALISE_FREEONCLOSE flag that will notify sqlite3_deserialize to manage the buffer and free the allocation when it's done with it.

Notes

This still needs testing, but I wanted to first understand if there are other changes needed for this implementation.

Also, I really doubt that the Err I've implemented are correct, I'd need some guidance on how we should handle those failures

Looking forward to your feedback, thanks!

@mattrighetti mattrighetti changed the title feat: sqlx sqlite expose serialize feat: sqlx sqlite expose de/serialize Feb 16, 2025
- pass non-owned byte slice to deserialize
- `SqliteBufError` and better error handling
- more impl for `SqliteOnwedBuf` so it can be used as a slice
- default serialize for `SqliteConnection`
@mattrighetti mattrighetti force-pushed the feat/sqlx-sqlite-expose-serialize branch from d46771b to ee4d3fc Compare February 19, 2025 02:35
@mattrighetti
Copy link
Contributor Author

I've implemented the serialize method on SqliteConnection so that it returns an SqliteOwnedBuf. I'm still unwrapping some type conversions, I'll fix those in a follow-up change.

It would be cool to have a single serialize function on SqliteConnection which could return both the default and the nocopy buffers but I still have to figure out how to achieve the latter.

@mattrighetti
Copy link
Contributor Author

mattrighetti commented Feb 20, 2025

Update: I've moved serialize() and deserialize() on the worker thread but I have little knowledge of the codebase so feel free to point me in the right direction.

I had to introduce two new Command enumerations Serialize + Deserialize so that they can be used and passed in the worker tx channel.

serialize() probably requires more work, as @abonander pointed out

it may have to wait for concurrent write transactions from other connections to complete

plus, I've implemented Send + Sync for SqliteOwnedBuf just to silence the compiler complaints because NonNull<u8> is not thread-safe ofc.

I've also removed the NOCOPY implementation until we figure out how to handle that.

This implements `Command::Serialize` and `Command::Deserialize` and moves the
serialize and deserialize logic to the worker thread.

`Serialize` will need some more iterations as it's not clear whether it would
need to wait for other write transactions before running.
@mattrighetti mattrighetti force-pushed the feat/sqlx-sqlite-expose-serialize branch from f7f5d7c to 782952a Compare February 20, 2025 23:00
mattrighetti and others added 3 commits February 28, 2025 00:18
- Merged deserialize module with serialize module
- Moved `SqliteOwnedBuf` into serialize module
- Fixed rustdocs
@abonander
Copy link
Collaborator

@mattrighetti on further review, there were a lot of things I wanted to change and it would have been unwieldy to do it all in review comments. I took the liberty of pushing a commit with the changes:

  • expanded docs better matching the style of the rest of the project
  • better error handling
  • integration tests

Take a look and let me know what you think.

@mattrighetti
Copy link
Contributor Author

lgtm!

Not 100% convinced about the serialize(Option<&str>) but I guess it makes sense for this first iteration.

In the future we could introduce a new function serialize_schema(&str) where we explicitly ask for a schema while keeping serialize() as "main" schema serialization.

@abonander abonander merged commit c5ea6c4 into launchbadge:main Mar 2, 2025
81 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.

2 participants