Skip to content

Commit 0d7c91e

Browse files
committed
add support for coalesce in function calls
1 parent 6067aa2 commit 0d7c91e

File tree

4 files changed

+34
-0
lines changed

4 files changed

+34
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
- Fix a bug where the `sqlpage.environment_variable` function would return an error if the environment variable was not set. Now it returns `null` instead.
3434
- Update ApexCharts to [v4.3.0](https://github.com/apexcharts/apexcharts.js/releases/tag/v4.3.0).
3535
- New `article` property in the text component to display text in a more readable, article-like format.
36+
- Add support for evaluating calls to `coalesce` inside sqlpage functions. This means you can now use `coalesce` inside arguments of sqlpage functions, and it will be evaluated inside sqlpage. For instance, this lets you call `sqlpage.link(coalesce($url, 'https://sql-page.com'))` to create a link that will use the value of `$url` if it is not null, or fallback to `https://sql-page.com` if it is null.
3637

3738
## 0.31.0 (2024-11-24)
3839

src/webserver/database/sql.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,12 @@ fn expr_to_stmt_param(arg: &mut Expr) -> Option<StmtParam> {
659659
json_obj_args.push(function_arg_to_stmt_param(arg)?);
660660
}
661661
Some(StmtParam::JsonArray(json_obj_args))
662+
} else if func_name.eq_ignore_ascii_case("coalesce") {
663+
let mut coalesce_args = Vec::with_capacity(args.len());
664+
for arg in args {
665+
coalesce_args.push(function_arg_to_stmt_param(arg)?);
666+
}
667+
Some(StmtParam::Coalesce(coalesce_args))
662668
} else {
663669
log::warn!("SQLPage cannot emulate the following function: {func_name}");
664670
None

src/webserver/database/syntax_tree.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub(crate) enum StmtParam {
3838
Literal(String),
3939
Null,
4040
Concat(Vec<StmtParam>),
41+
Coalesce(Vec<StmtParam>),
4142
JsonObject(Vec<StmtParam>),
4243
JsonArray(Vec<StmtParam>),
4344
FunctionCall(SqlPageFunctionCall),
@@ -58,6 +59,13 @@ impl std::fmt::Display for StmtParam {
5859
}
5960
write!(f, ")")
6061
}
62+
StmtParam::Coalesce(items) => {
63+
write!(f, "COALESCE(")?;
64+
for item in items {
65+
write!(f, "{item}, ")?;
66+
}
67+
write!(f, ")")
68+
}
6169
StmtParam::JsonObject(items) => {
6270
write!(f, "JSON_OBJECT(")?;
6371
for item in items {
@@ -163,6 +171,7 @@ pub(super) async fn extract_req_param<'a, 'b>(
163171
StmtParam::Concat(args) => concat_params(&args[..], request, db_connection).await?,
164172
StmtParam::JsonObject(args) => json_object_params(&args[..], request, db_connection).await?,
165173
StmtParam::JsonArray(args) => json_array_params(&args[..], request, db_connection).await?,
174+
StmtParam::Coalesce(args) => coalesce_params(&args[..], request, db_connection).await?,
166175
StmtParam::FunctionCall(func) => func.evaluate(request, db_connection).await.with_context(|| {
167176
format!(
168177
"Error in function call {func}.\nExpected {:#}",
@@ -187,6 +196,19 @@ async fn concat_params<'a, 'b>(
187196
Ok(Some(Cow::Owned(result)))
188197
}
189198

199+
async fn coalesce_params<'a, 'b>(
200+
args: &[StmtParam],
201+
request: &'a RequestInfo,
202+
db_connection: &'b mut DbConn,
203+
) -> anyhow::Result<Option<Cow<'a, str>>> {
204+
for arg in args {
205+
if let Some(arg) = Box::pin(extract_req_param(arg, request, db_connection)).await? {
206+
return Ok(Some(arg));
207+
}
208+
}
209+
Ok(None)
210+
}
211+
190212
async fn json_object_params<'a, 'b>(
191213
args: &[StmtParam],
192214
request: &'a RequestInfo,
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(coalesce($i_do_not_exist, 'https://example.com'))
3+
when 'https://example.com' then 'It works !'
4+
else 'error: ' || coalesce(sqlpage.link(coalesce($i_do_not_exist, 'https://example.com')), 'NULL')
5+
end AS contents;

0 commit comments

Comments
 (0)