mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-18 09:04:19 +01:00
treat parameters as "constant" within a query
This commit is contained in:
@@ -1071,7 +1071,7 @@ impl Optimizable for ast::Expr {
|
||||
Expr::Register(..) => false, // Register values can be null
|
||||
}
|
||||
}
|
||||
/// Returns true if the expression is a constant i.e. does not depend on variables or columns etc.
|
||||
/// Returns true if the expression is a constant i.e. does not depend on columns and can be evaluated only once during the execution
|
||||
fn is_constant(&self, resolver: &Resolver<'_>) -> bool {
|
||||
match self {
|
||||
Expr::SubqueryResult { .. } => false,
|
||||
@@ -1142,8 +1142,8 @@ impl Optimizable for ast::Expr {
|
||||
Expr::Raise(_, expr) => expr.as_ref().is_none_or(|expr| expr.is_constant(resolver)),
|
||||
Expr::Subquery(_) => false,
|
||||
Expr::Unary(_, expr) => expr.is_constant(resolver),
|
||||
Expr::Variable(_) => false,
|
||||
Expr::Register(_) => false, // Register values are not constants
|
||||
Expr::Variable(_) => true,
|
||||
Expr::Register(_) => true,
|
||||
}
|
||||
}
|
||||
/// Returns true if the expression is a constant expression that, when evaluated as a condition, is always true or false
|
||||
|
||||
@@ -1018,3 +1018,47 @@ fn test_many_columns() {
|
||||
]]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_eval_param_only_once() {
|
||||
let tmp_db = TempDatabase::new("test_eval_param_only_once");
|
||||
let conn = tmp_db.connect_limbo();
|
||||
conn.execute("CREATE TABLE t(x)").unwrap();
|
||||
conn.execute("INSERT INTO t SELECT value FROM generate_series(1, 10000)")
|
||||
.unwrap();
|
||||
let mut stmt = conn
|
||||
.query("SELECT COUNT(*) FROM t WHERE LENGTH(zeroblob(?)) = ?")
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
stmt.bind_at(
|
||||
1.try_into().unwrap(),
|
||||
turso_core::Value::Integer(100_000_000),
|
||||
);
|
||||
stmt.bind_at(
|
||||
2.try_into().unwrap(),
|
||||
turso_core::Value::Integer(100_000_000),
|
||||
);
|
||||
let start_time = std::time::Instant::now();
|
||||
loop {
|
||||
match stmt.step().unwrap() {
|
||||
StepResult::IO => {
|
||||
stmt.run_once().unwrap();
|
||||
}
|
||||
StepResult::Done => break,
|
||||
StepResult::Row => {
|
||||
let values = stmt
|
||||
.row()
|
||||
.unwrap()
|
||||
.get_values()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(values, vec![turso_core::Value::Integer(10000)]);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
let end_time = std::time::Instant::now();
|
||||
let elapsed = end_time.duration_since(start_time);
|
||||
// the test will allocate 10^8 * 10^4 bytes in case if parameter will be evaluated for every row
|
||||
assert!(elapsed < std::time::Duration::from_millis(100));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user