Skip to content

Commit b7ceef9

Browse files
cursoragentlovasoa
andcommitted
Refactor variable system for immutability and clarity
Co-authored-by: contact <[email protected]>
2 parents abc0a22 + b11e7bf commit b7ceef9

File tree

3 files changed

+39
-18
lines changed

3 files changed

+39
-18
lines changed

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
11
# CHANGELOG.md
22

33
## unrelease
4+
- **Variable System Improvements**: URL and POST parameters are now immutable, preventing accidental modification. User-defined variables created with `SET` remain mutable.
5+
- **BREAKING**: `$variable` no longer accesses POST parameters. Use `:variable` instead.
6+
- **What changed**: Previously, `$x` would return a POST parameter value if no GET parameter named `x` existed.
7+
- **Fix**: Replace `$x` with `:x` when you need to access form field values.
8+
- **Example**: Change `SELECT $username` to `SELECT :username` when reading form submissions.
9+
- **BREAKING**: `SET $name` no longer overwrites GET (URL) parameters when a URL parameter with the same name exists.
10+
- **What changed**: `SET $name = 'value'` would previously overwrite the URL parameter `$name`. Now it creates an independent SET variable that shadows the URL parameter.
11+
- **Fix**: This is generally the desired behavior. If you need to access the original URL parameter after setting a variable with the same name, extract it from the JSON returned by `sqlpage.variables('get')`.
12+
- **Example**: If your URL is `page.sql?name=john`, and you do `SET $name = 'modified'`, then:
13+
- `$name` will be `'modified'` (the SET variable)
14+
- The original URL parameter is still preserved and accessible:
15+
- PostgreSQL: `sqlpage.variables('get')->>'name'` returns `'john'`
16+
- SQLite: `json_extract(sqlpage.variables('get'), '$.name')` returns `'john'`
17+
- MySQL: `JSON_UNQUOTE(JSON_EXTRACT(sqlpage.variables('get'), '$.name'))` returns `'john'`
18+
- **New behavior**: Variable lookup now follows this precedence:
19+
- `$variable` checks SET variables first, then URL parameters
20+
- `:variable` checks SET variables first, then POST parameters
21+
- SET variables always shadow URL/POST parameters with the same name
22+
- **New sqlpage.variables() filters**:
23+
- `sqlpage.variables('get')` returns only URL parameters as JSON
24+
- `sqlpage.variables('post')` returns only POST parameters as JSON
25+
- `sqlpage.variables('set')` returns only user-defined SET variables as JSON
26+
- `sqlpage.variables()` returns all variables merged together, with SET variables taking precedence
27+
- **Deprecation warnings**: Using `$var` when both a URL parameter and POST parameter exist with the same name now shows a warning. In a future version, you'll need to explicitly choose between `$var` (URL) and `:var` (POST).
428
- add support for postgres range types
529

630
## v0.39.1 (2025-11-08)

src/webserver/database/syntax_tree.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,21 +169,20 @@ pub(super) async fn extract_req_param<'a>(
169169
Some(Cow::Owned(val.as_json_str().into_owned()))
170170
} else {
171171
let url_val = request.url_params.get(x);
172-
let post_val = request.post_variables.get(x);
173-
if let Some(post_val) = post_val {
174-
if let Some(url_val) = url_val {
172+
if request.post_variables.contains_key(x) {
173+
if url_val.is_some() {
175174
log::warn!(
176-
"Deprecation warning! There is both a URL parameter named '{x}' with value '{url_val}' and a form field named '{x}' with value '{post_val}'. \
177-
SQLPage is using the value from the form submission, but this is ambiguous, can lead to unexpected behavior, and will stop working in a future version of SQLPage. \
178-
To fix this, please rename the URL parameter to something else, and reference the form field with :{x}."
175+
"Deprecation warning! There is both a URL parameter named '{x}' and a form field named '{x}'. \
176+
SQLPage is using the URL parameter for ${x}. Please use :{x} to reference the form field explicitly."
179177
);
180178
} else {
181-
log::warn!("Deprecation warning! ${x} was used to reference a form field value (a POST variable) instead of a URL parameter. This will stop working soon. Please use :{x} instead.");
179+
log::warn!(
180+
"Deprecation warning! ${x} was used to reference a form field value (a POST variable). \
181+
This now uses only URL parameters. Please use :{x} instead."
182+
);
182183
}
183-
Some(post_val.as_json_str())
184-
} else {
185-
url_val.map(SingleOrVec::as_json_str)
186184
}
185+
url_val.map(SingleOrVec::as_json_str)
187186
}
188187
}
189188
StmtParam::Error(x) => anyhow::bail!("{x}"),

tests/sql_test_files/it_works_immutable_variables.sql

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,17 @@ SELECT CASE
1515
END AS contents;
1616

1717
SELECT CASE
18-
WHEN json_extract(sqlpage.variables('get'), '$.x') = '1' THEN 'It works !'
19-
ELSE 'FAIL: variables(''get'') should return only URL parameters'
18+
WHEN sqlpage.variables('get') = '{"x":"1"}' THEN 'It works !'
19+
ELSE 'FAIL: variables(''get'') should return only URL parameters, got: ' || sqlpage.variables('get')
2020
END AS contents;
2121

2222
SELECT CASE
23-
WHEN json_extract(sqlpage.variables('set'), '$.x') = 'set_value' AND
24-
json_extract(sqlpage.variables('set'), '$.set_only') = 'only_in_set' THEN 'It works !'
25-
ELSE 'FAIL: variables(''set'') should return only SET variables'
23+
WHEN sqlpage.variables('set') = '{"x":"set_value","set_only":"only_in_set"}' THEN 'It works !'
24+
ELSE 'FAIL: variables(''set'') should return only SET variables, got: ' || sqlpage.variables('set')
2625
END AS contents;
2726

2827
SELECT CASE
29-
WHEN json_extract(sqlpage.variables(), '$.x') = 'set_value' AND
30-
json_extract(sqlpage.variables(), '$.set_only') = 'only_in_set' THEN 'It works !'
31-
ELSE 'FAIL: variables() should merge all with SET taking precedence'
28+
WHEN sqlpage.variables() = '{"x":"set_value","set_only":"only_in_set"}' THEN 'It works !'
29+
ELSE 'FAIL: variables() should merge all with SET taking precedence, got: ' || sqlpage.variables()
3230
END AS contents;
3331

0 commit comments

Comments
 (0)