mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-23 00:45:37 +01:00
Support binary math functions
This commit is contained in:
@@ -169,7 +169,7 @@ Feature support of [sqlite expr syntax](https://www.sqlite.org/lang_expr.html).
|
||||
| asin(X) | Yes | |
|
||||
| asinh(X) | Yes | |
|
||||
| atan(X) | Yes | |
|
||||
| atan2(Y,X) | No | |
|
||||
| atan2(Y,X) | Yes | |
|
||||
| atanh(X) | Yes | |
|
||||
| ceil(X) | Yes | |
|
||||
| ceiling(X) | Yes | |
|
||||
@@ -183,10 +183,10 @@ Feature support of [sqlite expr syntax](https://www.sqlite.org/lang_expr.html).
|
||||
| log(X) | No | |
|
||||
| log10(X) | Yes | |
|
||||
| log2(X) | Yes | |
|
||||
| mod(X,Y) | No | |
|
||||
| mod(X,Y) | Yes | |
|
||||
| pi() | No | |
|
||||
| pow(X,Y) | No | |
|
||||
| power(X,Y) | No | |
|
||||
| pow(X,Y) | Yes | |
|
||||
| power(X,Y) | Yes | |
|
||||
| radians(X) | Yes | |
|
||||
| sin(X) | Yes | |
|
||||
| sinh(X) | Yes | |
|
||||
|
||||
@@ -1635,6 +1635,53 @@ pub fn translate_expr(
|
||||
});
|
||||
Ok(target_register)
|
||||
}
|
||||
|
||||
MathFuncArity::Binary => {
|
||||
let args = if let Some(args) = args {
|
||||
if args.len() != 2 {
|
||||
crate::bail_parse_error!(
|
||||
"{} function with not exactly 2 arguments",
|
||||
math_func
|
||||
);
|
||||
}
|
||||
args
|
||||
} else {
|
||||
crate::bail_parse_error!("{} function with no arguments", math_func);
|
||||
};
|
||||
|
||||
let reg1 = program.alloc_register();
|
||||
let reg2 = program.alloc_register();
|
||||
|
||||
translate_expr(
|
||||
program,
|
||||
referenced_tables,
|
||||
&args[0],
|
||||
reg1,
|
||||
precomputed_exprs_to_registers,
|
||||
)?;
|
||||
if let ast::Expr::Literal(_) = &args[0] {
|
||||
program.mark_last_insn_constant();
|
||||
}
|
||||
|
||||
translate_expr(
|
||||
program,
|
||||
referenced_tables,
|
||||
&args[1],
|
||||
reg2,
|
||||
precomputed_exprs_to_registers,
|
||||
)?;
|
||||
if let ast::Expr::Literal(_) = &args[1] {
|
||||
program.mark_last_insn_constant();
|
||||
}
|
||||
|
||||
program.emit_insn(Insn::Function {
|
||||
constant_mask: 0,
|
||||
start_reg: target_register + 1,
|
||||
dest: target_register,
|
||||
func: func_ctx,
|
||||
});
|
||||
Ok(target_register)
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2497,6 +2497,13 @@ impl Program {
|
||||
let result = exec_math_unary(reg_value, math_func);
|
||||
state.registers[*dest] = result;
|
||||
}
|
||||
|
||||
MathFuncArity::Binary => {
|
||||
let lhs = &state.registers[*start_reg];
|
||||
let rhs = &state.registers[*start_reg + 1];
|
||||
let result = exec_math_binary(lhs, rhs, math_func);
|
||||
state.registers[*dest] = result;
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
crate::function::Func::Agg(_) => {
|
||||
@@ -3662,6 +3669,31 @@ fn exec_math_unary(reg: &OwnedValue, function: &MathFunc) -> OwnedValue {
|
||||
}
|
||||
}
|
||||
|
||||
fn exec_math_binary(lhs: &OwnedValue, rhs: &OwnedValue, function: &MathFunc) -> OwnedValue {
|
||||
let lhs = match to_f64(lhs) {
|
||||
Some(f) => f,
|
||||
None => return OwnedValue::Null,
|
||||
};
|
||||
|
||||
let rhs = match to_f64(rhs) {
|
||||
Some(f) => f,
|
||||
None => return OwnedValue::Null,
|
||||
};
|
||||
|
||||
let result = match function {
|
||||
MathFunc::Atan2 => lhs.atan2(rhs),
|
||||
MathFunc::Mod => lhs % rhs,
|
||||
MathFunc::Pow | MathFunc::Power => lhs.powf(rhs),
|
||||
_ => unreachable!("Unexpected mathematical binary function {:?}", function),
|
||||
};
|
||||
|
||||
if result.is_nan() {
|
||||
OwnedValue::Null
|
||||
} else {
|
||||
OwnedValue::Float(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
|
||||
@@ -791,3 +791,183 @@ do_execsql_test trunc-str {
|
||||
do_execsql_test trunc-null {
|
||||
SELECT trunc(null)
|
||||
} {}
|
||||
|
||||
|
||||
do_execsql_test_tolerance atan2-int-int {
|
||||
SELECT atan2(5, -1)
|
||||
} {1.76819188664478} $tolerance
|
||||
|
||||
do_execsql_test_tolerance atan2-int-float {
|
||||
SELECT atan2(5, -1.5)
|
||||
} {1.86225312127276} $tolerance
|
||||
|
||||
do_execsql_test_tolerance atan2-int-str {
|
||||
SELECT atan2(5, '-1.5')
|
||||
} {1.86225312127276} $tolerance
|
||||
|
||||
do_execsql_test_tolerance atan2-float-int {
|
||||
SELECT atan2(5.5, 10)
|
||||
} {0.502843210927861} $tolerance
|
||||
|
||||
do_execsql_test_tolerance atan2-float-float {
|
||||
SELECT atan2(5.5, -1.5)
|
||||
} {1.83704837594582} $tolerance
|
||||
|
||||
do_execsql_test_tolerance atan2-float-str {
|
||||
SELECT atan2(5.5, '-1.5')
|
||||
} {1.83704837594582} $tolerance
|
||||
|
||||
do_execsql_test_tolerance atan2-str-str {
|
||||
SELECT atan2('5.5', '-1.5')
|
||||
} {1.83704837594582} $tolerance
|
||||
|
||||
do_execsql_test atan2-null-int {
|
||||
SELECT atan2(null, 5)
|
||||
} {}
|
||||
|
||||
do_execsql_test atan2-int-null {
|
||||
SELECT atan2(5, null)
|
||||
} {}
|
||||
|
||||
|
||||
do_execsql_test_tolerance mod-int-int {
|
||||
SELECT mod(10, -3)
|
||||
} {1.0} $tolerance
|
||||
|
||||
do_execsql_test_tolerance mod-int-float {
|
||||
SELECT mod(5, -1.5)
|
||||
} {0.5} $tolerance
|
||||
|
||||
do_execsql_test_tolerance mod-int-str {
|
||||
SELECT mod(5, '-1.5')
|
||||
} {0.5} $tolerance
|
||||
|
||||
do_execsql_test_tolerance mod-float-int {
|
||||
SELECT mod(5.5, 2)
|
||||
} {1.5} $tolerance
|
||||
|
||||
do_execsql_test_tolerance mod-float-float {
|
||||
SELECT mod(5.5, -1.5)
|
||||
} {1.0} $tolerance
|
||||
|
||||
do_execsql_test_tolerance mod-float-str {
|
||||
SELECT mod(5.5, '-1.5')
|
||||
} {1.0} $tolerance
|
||||
|
||||
do_execsql_test_tolerance mod-str-str {
|
||||
SELECT mod('5.5', '-1.5')
|
||||
} {1.0} $tolerance
|
||||
|
||||
do_execsql_test mod-null-int {
|
||||
SELECT mod(null, 5)
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-int-null {
|
||||
SELECT mod(5, null)
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-float-zero {
|
||||
SELECT mod(1.5, 0)
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-products-id {
|
||||
SELECT mod(products.id, 3) from products
|
||||
} {1.0
|
||||
2.0
|
||||
0.0
|
||||
1.0
|
||||
2.0
|
||||
0.0
|
||||
1.0
|
||||
2.0
|
||||
0.0
|
||||
1.0
|
||||
2.0}
|
||||
|
||||
do_execsql_test mod-products-price-id {
|
||||
SELECT mod(products.price, products.id) from products
|
||||
} {0.0
|
||||
0.0
|
||||
0.0
|
||||
1.0
|
||||
4.0
|
||||
4.0
|
||||
1.0
|
||||
2.0
|
||||
1.0
|
||||
3.0
|
||||
4.0}
|
||||
|
||||
|
||||
do_execsql_test_tolerance pow-int-int {
|
||||
SELECT pow(5, -1)
|
||||
} {0.2} $tolerance
|
||||
|
||||
do_execsql_test_tolerance pow-int-float {
|
||||
SELECT pow(5, -1.5)
|
||||
} {0.0894427190999916} $tolerance
|
||||
|
||||
do_execsql_test_tolerance pow-int-str {
|
||||
SELECT pow(5, '-1.5')
|
||||
} {0.0894427190999916} $tolerance
|
||||
|
||||
do_execsql_test_tolerance pow-float-int {
|
||||
SELECT pow(5.5, 2)
|
||||
} {30.25} $tolerance
|
||||
|
||||
do_execsql_test_tolerance pow-float-float {
|
||||
SELECT pow(5.5, -1.5)
|
||||
} {0.077527533220222} $tolerance
|
||||
|
||||
do_execsql_test_tolerance pow-float-str {
|
||||
SELECT pow(5.5, '-1.5')
|
||||
} {0.077527533220222} $tolerance
|
||||
|
||||
do_execsql_test_tolerance pow-str-str {
|
||||
SELECT pow('5.5', '-1.5')
|
||||
} {0.077527533220222} $tolerance
|
||||
|
||||
do_execsql_test pow-null-int {
|
||||
SELECT pow(null, 5)
|
||||
} {}
|
||||
|
||||
do_execsql_test pow-int-null {
|
||||
SELECT pow(5, null)
|
||||
} {}
|
||||
|
||||
|
||||
do_execsql_test_tolerance power-int-int {
|
||||
SELECT power(5, -1)
|
||||
} {0.2} $tolerance
|
||||
|
||||
do_execsql_test_tolerance power-int-float {
|
||||
SELECT power(5, -1.5)
|
||||
} {0.0894427190999916} $tolerance
|
||||
|
||||
do_execsql_test_tolerance power-int-str {
|
||||
SELECT power(5, '-1.5')
|
||||
} {0.0894427190999916} $tolerance
|
||||
|
||||
do_execsql_test_tolerance power-float-int {
|
||||
SELECT power(5.5, 2)
|
||||
} {30.25} $tolerance
|
||||
|
||||
do_execsql_test_tolerance power-float-float {
|
||||
SELECT power(5.5, -1.5)
|
||||
} {0.077527533220222} $tolerance
|
||||
|
||||
do_execsql_test_tolerance power-float-str {
|
||||
SELECT power(5.5, '-1.5')
|
||||
} {0.077527533220222} $tolerance
|
||||
|
||||
do_execsql_test_tolerance power-str-str {
|
||||
SELECT power('5.5', '-1.5')
|
||||
} {0.077527533220222} $tolerance
|
||||
|
||||
do_execsql_test power-null-int {
|
||||
SELECT power(null, 5)
|
||||
} {}
|
||||
|
||||
do_execsql_test power-int-null {
|
||||
SELECT power(5, null)
|
||||
} {}
|
||||
|
||||
Reference in New Issue
Block a user