Fix delimiter handling in group_concat and string_agg

Non-literal delimiters must be translated by AggArgumentSource.
This commit is contained in:
Piotr Rzysko
2025-09-05 20:49:03 +02:00
parent 110ffba2a1
commit 6d84cbedc2
2 changed files with 41 additions and 30 deletions

View File

@@ -312,33 +312,26 @@ pub fn translate_aggregation_step(
crate::bail_parse_error!("group_concat bad number of arguments"); crate::bail_parse_error!("group_concat bad number of arguments");
} }
let delimiter_reg = program.alloc_register(); let delimiter_reg = if num_args == 2 {
let delimiter_expr: ast::Expr;
if num_args == 2 {
match &agg_arg_source.args()[1] { match &agg_arg_source.args()[1] {
arg @ ast::Expr::Column { .. } => { ast::Expr::Column { .. } => {
delimiter_expr = arg.clone(); agg_arg_source.translate(program, referenced_tables, resolver, 1)?
} }
ast::Expr::Literal(ast::Literal::String(s)) => { ast::Expr::Literal(ast::Literal::String(s)) => {
delimiter_expr = ast::Expr::Literal(ast::Literal::String(s.to_string())); let delimiter_expr =
ast::Expr::Literal(ast::Literal::String(s.to_string()));
translate_const_arg(program, referenced_tables, resolver, &delimiter_expr)?
} }
_ => crate::bail_parse_error!("Incorrect delimiter parameter"), _ => crate::bail_parse_error!("Incorrect delimiter parameter"),
}; }
} else { } else {
delimiter_expr = ast::Expr::Literal(ast::Literal::String(String::from("\",\""))); let delimiter_expr =
} ast::Expr::Literal(ast::Literal::String(String::from("\",\"")));
translate_const_arg(program, referenced_tables, resolver, &delimiter_expr)?
};
let expr_reg = agg_arg_source.translate(program, referenced_tables, resolver, 0)?; let expr_reg = agg_arg_source.translate(program, referenced_tables, resolver, 0)?;
handle_distinct(program, agg_arg_source.aggregate(), expr_reg); handle_distinct(program, agg_arg_source.aggregate(), expr_reg);
translate_expr(
program,
Some(referenced_tables),
&delimiter_expr,
delimiter_reg,
resolver,
)?;
program.emit_insn(Insn::AggStep { program.emit_insn(Insn::AggStep {
acc_reg: target_register, acc_reg: target_register,
@@ -418,24 +411,18 @@ pub fn translate_aggregation_step(
crate::bail_parse_error!("string_agg bad number of arguments"); crate::bail_parse_error!("string_agg bad number of arguments");
} }
let delimiter_reg = program.alloc_register(); let delimiter_reg = match &agg_arg_source.args()[1] {
ast::Expr::Column { .. } => {
let delimiter_expr = match &agg_arg_source.args()[1] { agg_arg_source.translate(program, referenced_tables, resolver, 1)?
arg @ ast::Expr::Column { .. } => arg.clone(), }
ast::Expr::Literal(ast::Literal::String(s)) => { ast::Expr::Literal(ast::Literal::String(s)) => {
ast::Expr::Literal(ast::Literal::String(s.to_string())) let delimiter_expr = ast::Expr::Literal(ast::Literal::String(s.to_string()));
translate_const_arg(program, referenced_tables, resolver, &delimiter_expr)?
} }
_ => crate::bail_parse_error!("Incorrect delimiter parameter"), _ => crate::bail_parse_error!("Incorrect delimiter parameter"),
}; };
let expr_reg = agg_arg_source.translate(program, referenced_tables, resolver, 0)?; let expr_reg = agg_arg_source.translate(program, referenced_tables, resolver, 0)?;
translate_expr(
program,
Some(referenced_tables),
&delimiter_expr,
delimiter_reg,
resolver,
)?;
program.emit_insn(Insn::AggStep { program.emit_insn(Insn::AggStep {
acc_reg: target_register, acc_reg: target_register,
@@ -506,3 +493,19 @@ pub fn translate_aggregation_step(
}; };
Ok(dest) Ok(dest)
} }
fn translate_const_arg(
program: &mut ProgramBuilder,
referenced_tables: &TableReferences,
resolver: &Resolver,
expr: &ast::Expr,
) -> Result<usize> {
let target_register = program.alloc_register();
translate_expr(
program,
Some(referenced_tables),
expr,
target_register,
resolver,
)
}

View File

@@ -88,6 +88,10 @@ do_execsql_test select-group-concat-with-column-delimiter {
SELECT group_concat(name, id) FROM products; SELECT group_concat(name, id) FROM products;
} {hat2cap3shirt4sweater5sweatshirt6shorts7jeans8sneakers9boots10coat11accessories} } {hat2cap3shirt4sweater5sweatshirt6shorts7jeans8sneakers9boots10coat11accessories}
do_execsql_test select-group-concat-with-column-delimiter-group-by {
SELECT group_concat(name, id) FROM products GROUP BY '1';
} {hat2cap3shirt4sweater5sweatshirt6shorts7jeans8sneakers9boots10coat11accessories}
do_execsql_test select-string-agg-with-delimiter { do_execsql_test select-string-agg-with-delimiter {
SELECT string_agg(name, ',') FROM products; SELECT string_agg(name, ',') FROM products;
} {hat,cap,shirt,sweater,sweatshirt,shorts,jeans,sneakers,boots,coat,accessories} } {hat,cap,shirt,sweater,sweatshirt,shorts,jeans,sneakers,boots,coat,accessories}
@@ -96,6 +100,10 @@ do_execsql_test select-string-agg-with-column-delimiter {
SELECT string_agg(name, id) FROM products; SELECT string_agg(name, id) FROM products;
} {hat2cap3shirt4sweater5sweatshirt6shorts7jeans8sneakers9boots10coat11accessories} } {hat2cap3shirt4sweater5sweatshirt6shorts7jeans8sneakers9boots10coat11accessories}
do_execsql_test select-string-agg-with-column-delimiter-group-by {
SELECT string_agg(name, id) FROM products GROUP BY '1';
} {hat2cap3shirt4sweater5sweatshirt6shorts7jeans8sneakers9boots10coat11accessories}
do_execsql_test select-agg-unary-negative { do_execsql_test select-agg-unary-negative {
SELECT -max(age) FROM users; SELECT -max(age) FROM users;
} {-100} } {-100}