Skip to content

Commit b04f021

Browse files
committed
Fix handling of NULL values in sqlpage.link
NULL values were encoded as the string `'null'` instead of being omitted from the link's parameters.
1 parent 9ff1d9f commit b04f021

File tree

4 files changed

+27
-4
lines changed

4 files changed

+27
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## O.37.1
44
- fixed decoding of UUID values
5+
- Fixed handling of NULL values in `sqlpage.link`. They were encoded as the string `'null'` instead of being omitted from the link's parameters.
56

67
## v0.37.0
78
- We now cryptographically sign the Windows app during releases, which proves the file hasn’t been tampered with. Once the production certificate is active, Windows will show a "verified publisher" and should stop showing screens saying "This app might harm your device", "Windows protected your PC" or "Are you sure you want to run this application ?".

src/webserver/database/sqlpage_functions/functions.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,11 +372,14 @@ async fn link<'a>(
372372
) -> anyhow::Result<String> {
373373
let mut url = file.into_owned();
374374
if let Some(parameters) = parameters {
375-
url.push('?');
376375
let encoded = serde_json::from_str::<URLParameters>(&parameters).with_context(|| {
377376
format!("link: invalid URL parameters: not a valid json object:\n{parameters}")
378377
})?;
379-
url.push_str(encoded.get());
378+
let encoded_str = encoded.get();
379+
if !encoded_str.is_empty() {
380+
url.push('?');
381+
url.push_str(encoded_str);
382+
}
380383
}
381384
if let Some(hash) = hash {
382385
url.push('#');

src/webserver/database/sqlpage_functions/url_parameter_deserializer.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ impl<'de> Deserialize<'de> for URLParameters {
4848
map.next_entry::<Cow<str>, Cow<serde_json::value::RawValue>>()?
4949
{
5050
let value = value.get();
51-
if let Ok(str_val) = serde_json::from_str::<Cow<str>>(value) {
52-
out.push_kv(&key, &str_val);
51+
if let Ok(str_val) = serde_json::from_str::<Option<Cow<str>>>(value) {
52+
if let Some(str_val) = str_val {
53+
out.push_kv(&key, &str_val);
54+
}
5355
} else if let Ok(vec_val) =
5456
serde_json::from_str::<Vec<serde_json::Value>>(value)
5557
{
@@ -96,6 +98,18 @@ fn test_url_parameters_deserializer() {
9698
);
9799
}
98100

101+
#[test]
102+
fn test_url_parameters_null() {
103+
use serde_json::json;
104+
let json = json!({
105+
"null_should_be_omitted": null,
106+
"x": "hello",
107+
});
108+
109+
let url_parameters: URLParameters = serde_json::from_value(json).unwrap();
110+
assert_eq!(url_parameters.0, "x=hello");
111+
}
112+
99113
#[test]
100114
fn test_url_parameters_deserializer_special_chars() {
101115
use serde_json::json;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
select 'text' as component,
2+
case sqlpage.link('test.sql', json_object('x', null))
3+
when 'test.sql' then 'It works !'
4+
else 'error: ' || coalesce(sqlpage.link('test.sql', json_object('x', null)), 'NULL')
5+
end AS contents;

0 commit comments

Comments
 (0)