-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add SQLite support for serde_json::Value using the Json/Jsonb #4284
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for opening this PR. This is already a good starting point, but we need to adjust the (de)serialization of the jsonb type to match the actual underlying SQLite data format. Additionally tests + documentation need some tweaks.
Finally it would be great to have a changelog entry for this change.
18e3a95
to
eea59fd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update. It looks now much closer to what I had in mind here. I think we still should improve the test situation by adding more tests for jsonb roundtrips. We also might want to have a few tests that load data from the database and check that the expected result comes back. Finally it seems like that the handling of escaped string sequences is still missing from the parser/writer implementation. This should also be covered by tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update. I feel we are mostly there now. I've added a few minor remarks otherwise I would like to see an entry into the Changelog.md
file in the repository root for this feature + at least a handful tests that are essentilally:
let res = diesel::select(sql::<Jsonb>("jsonb('{\"whatever\": 42}')")).get_result::<serde_json::Value>(conn).unwrap();
assert_eq!(res, serde_json::json!(…));
to verify that loading values also works
/// let inserted_address = insert_into(contacts) | ||
/// .values((name.eq("Claus"), address.eq(&santas_address))) | ||
/// .returning(address) | ||
/// .get_result::<serde_json::Value>(connection)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that fails on CI because support for get_result() for insert statements for sqlite is behind a feature flag.
diesel/src/sql_types/mod.rs
Outdated
/// } | ||
/// | ||
/// # #[cfg(all(feature = "sqlite", feature = "serde_json"))] | ||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to not duplicate the whole example. I suggest to just put the create table statement behind #[cfg(feature = "postgres")]
and #[cfg(feature = "sqlite")]
, as everything else is the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
diesel/src/sqlite/types/json.rs
Outdated
} | ||
|
||
// Read a JSON integer in canonical format (INT) | ||
fn read_jsonb_int(bytes: &[u8], payload_size: usize) -> deserialize::Result<serde_json::Value> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bytes should already be payload_size here, right? In that case we don't need to take another subslice below. (The same likely applies to the other read functions as well)
diesel/src/sqlite/types/json.rs
Outdated
return Err("Payload size exceeds the maximum allowed size of 2GB".into()); | ||
} | ||
|
||
let mut header = Vec::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We likely should use Vec::with_capacity()
here as we know the payload size beforehand?
|
@weiznich I just updated the description with the check list. Please update it if necessary. |
The added changes look fine so far, the only thing missing here is making the CI pass. That likely requires small adjustments to when the tests are run. For postgres they should be gated with |
@weiznich it gets deeper: since the doc for the
|
04a9a11
to
9d5bf4b
Compare
@weiznich Actually I think I found a good middle-ground. I'll let you know when the CI is green. |
c8ac82f
to
acaefe9
Compare
@weiznich the CI is green except for this: https://github.com/diesel-rs/diesel/actions/runs/11113502349/job/30877989999
|
@weiznich since:
I chose to upgrade the lower bound req to 0.9.0: e3b1f58 |
@weiznich CI is all green now. If you are OK with the current state of the PR, I will squash my changes, then rebase. Then you can merge them. |
diesel/Cargo.toml
Outdated
@@ -30,7 +30,7 @@ mysqlclient-src = { version = "0.1.0", optional = true } | |||
pq-sys = { version = ">=0.4.0, <0.7.0", optional = true } | |||
pq-src = { version = "0.3", optional = true } | |||
quickcheck = { version = "1.0.3", optional = true } | |||
serde_json = { version = ">=0.8.0, <2.0", optional = true } | |||
serde_json = { version = ">=0.9.0, <2.0", optional = true } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fear its not possible to change the minimal supported version here, as that's a breaking change. We would need to find a different solution for this. The question is how…
I likely need to have some time thinking about possible solutions if you don't have any suggestions.
I'm sorry that this turns up only in the end, but it's important to keep stability here.
059e51d
to
d7ec7d7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update. I'm sorry that I still have found something that needs to be changed, but the Jsonb
type shouldn't be gated behind the serde_json
feature. Only the actual ToSql
/FromSql
impls for serde_json::Value
should be gated, as you can use columns/values of those type without actually loading them from the database, e.g by converting them to string or just comparing single fields.
diesel/src/sql_types/mod.rs
Outdated
/// # fn main() {} | ||
/// ``` | ||
#[cfg(all( | ||
feature = "serde_json", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This types should be independent from the serde_json
feature. It's fine to gate the doc-test to that feature, but not the type.
7558709
to
e8179fe
Compare
e8179fe
to
de6b847
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for fixing and thanks again for working on this ❤️
I think the next step for json support in the SQLite backend is to add definitions for the built-in SQL functions to diesel. Especially adding the json
and jsonb
functions should make it much easier to actually use this work. If you are interested in working on that as well, just reach out and I will provide more details on how this should be done. That part should be much more straight forward than adding these impls, as we don't need to care about parsing complicated stuff.
@@ -0,0 +1,1073 @@ | |||
//! Support for JSON and JSONB values under PostgreSQL. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit - Should this comment be: //! Support for JSON and JSONB values under SQLite.
?
Great work! Hoping this lands on the next diesel version :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit - Should this comment be: //! Support for JSON and JSONB values under SQLite.?
Can you submit a PR to fix that?
Great work! Hoping this lands on the next diesel version :)
It will be part of the next diesel feature release, but as always: We don't give any other ETA than when it's done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you submit a PR to fix that?
Done: #4307
Implements #3918
FromSql<Json, Sqlite> for serde_json::Value
ToSql<Json, Sqlite> for serde_json::Value
FromSql<Jsonb, Sqlite> for serde_json::Value
ToSql<Jsonb, Sqlite> for serde_json::Value
FromSql<Json, Sqlite>
ToSql<Json, Sqlite>
FromSql<Jsonb, Sqlite>
ToSql<Jsonb, Sqlite>
CHANGELOG.md
[ ] Update the CI (if needed)(update: nope)