mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-28 21:44:21 +01:00
Merge 'Remainder vdbe opcode' from Preston Thorpe
Reviewed-by: Sonny <14060682+sonhmai@users.noreply.github.com> Closes #562
This commit is contained in:
@@ -395,7 +395,7 @@ Feature support of [sqlite expr syntax](https://www.sqlite.org/lang_expr.html).
|
||||
| ReadCookie | No |
|
||||
| Real | Yes |
|
||||
| RealAffinity | Yes |
|
||||
| Remainder | No |
|
||||
| Remainder | Yes |
|
||||
| ResetCount | No |
|
||||
| ResultRow | Yes |
|
||||
| Return | Yes |
|
||||
|
||||
@@ -693,6 +693,13 @@ pub fn translate_expr(
|
||||
dest: target_register,
|
||||
});
|
||||
}
|
||||
ast::Operator::Modulus => {
|
||||
program.emit_insn(Insn::Remainder {
|
||||
lhs: e1_reg,
|
||||
rhs: e2_reg,
|
||||
dest: target_register,
|
||||
});
|
||||
}
|
||||
ast::Operator::BitwiseAnd => {
|
||||
program.emit_insn(Insn::BitAnd {
|
||||
lhs: e1_reg,
|
||||
|
||||
@@ -82,6 +82,15 @@ pub fn insn_to_str(
|
||||
0,
|
||||
format!("r[{}]=~r[{}]", dest, reg),
|
||||
),
|
||||
Insn::Remainder { lhs, rhs, dest } => (
|
||||
"Remainder",
|
||||
*lhs as i32,
|
||||
*rhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=r[{}]%r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
Insn::Null { dest, dest_end } => (
|
||||
"Null",
|
||||
0,
|
||||
|
||||
103
core/vdbe/mod.rs
103
core/vdbe/mod.rs
@@ -119,6 +119,12 @@ pub enum Insn {
|
||||
reg: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Divide lhs by rhs and place the remainder in dest register.
|
||||
Remainder {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Jump to the instruction at address P1, P2, or P3 depending on whether in the most recent Compare instruction the P1 vector was less than, equal to, or greater than the P2 vector, respectively.
|
||||
Jump {
|
||||
target_pc_lt: BranchOffset,
|
||||
@@ -1224,6 +1230,103 @@ impl Program {
|
||||
}
|
||||
state.pc += 1;
|
||||
}
|
||||
Insn::Remainder { lhs, rhs, dest } => {
|
||||
let lhs = *lhs;
|
||||
let rhs = *rhs;
|
||||
let dest = *dest;
|
||||
state.registers[dest] = match (&state.registers[lhs], &state.registers[rhs]) {
|
||||
(OwnedValue::Null, _)
|
||||
| (_, OwnedValue::Null)
|
||||
| (_, OwnedValue::Integer(0))
|
||||
| (_, OwnedValue::Float(0.0)) => OwnedValue::Null,
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
|
||||
OwnedValue::Integer(lhs % rhs)
|
||||
}
|
||||
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => {
|
||||
OwnedValue::Float(((*lhs as i64) % (*rhs as i64)) as f64)
|
||||
}
|
||||
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => {
|
||||
OwnedValue::Float(((*lhs as i64) % rhs) as f64)
|
||||
}
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => {
|
||||
OwnedValue::Float((lhs % *rhs as i64) as f64)
|
||||
}
|
||||
(lhs, OwnedValue::Agg(agg_rhs)) => match lhs {
|
||||
OwnedValue::Agg(agg_lhs) => {
|
||||
let acc = agg_lhs.final_value();
|
||||
let acc2 = agg_rhs.final_value();
|
||||
match (acc, acc2) {
|
||||
(_, OwnedValue::Integer(0))
|
||||
| (_, OwnedValue::Float(0.0))
|
||||
| (_, OwnedValue::Null)
|
||||
| (OwnedValue::Null, _) => OwnedValue::Null,
|
||||
(OwnedValue::Integer(l), OwnedValue::Integer(r)) => {
|
||||
OwnedValue::Integer(l % r)
|
||||
}
|
||||
(OwnedValue::Float(lh_f), OwnedValue::Float(rh_f)) => {
|
||||
OwnedValue::Float(((*lh_f as i64) % (*rh_f as i64)) as f64)
|
||||
}
|
||||
(OwnedValue::Integer(lh_i), OwnedValue::Float(rh_f)) => {
|
||||
OwnedValue::Float((lh_i % (*rh_f as i64)) as f64)
|
||||
}
|
||||
_ => {
|
||||
todo!("{:?} {:?}", acc, acc2);
|
||||
}
|
||||
}
|
||||
}
|
||||
OwnedValue::Integer(lh_i) => match agg_rhs.final_value() {
|
||||
OwnedValue::Null => OwnedValue::Null,
|
||||
OwnedValue::Float(rh_f) => {
|
||||
OwnedValue::Float((lh_i % (*rh_f as i64)) as f64)
|
||||
}
|
||||
OwnedValue::Integer(rh_i) => OwnedValue::Integer(lh_i % rh_i),
|
||||
_ => {
|
||||
todo!("{:?}", agg_rhs);
|
||||
}
|
||||
},
|
||||
OwnedValue::Float(lh_f) => match agg_rhs.final_value() {
|
||||
OwnedValue::Null => OwnedValue::Null,
|
||||
OwnedValue::Float(rh_f) => {
|
||||
OwnedValue::Float(((*lh_f as i64) % (*rh_f as i64)) as f64)
|
||||
}
|
||||
OwnedValue::Integer(rh_i) => {
|
||||
OwnedValue::Float(((*lh_f as i64) % rh_i) as f64)
|
||||
}
|
||||
_ => {
|
||||
todo!("{:?}", agg_rhs);
|
||||
}
|
||||
},
|
||||
_ => todo!("{:?}", rhs),
|
||||
},
|
||||
(OwnedValue::Agg(aggctx), rhs) => match rhs {
|
||||
OwnedValue::Integer(rh_i) => match aggctx.final_value() {
|
||||
OwnedValue::Null => OwnedValue::Null,
|
||||
OwnedValue::Float(lh_f) => {
|
||||
OwnedValue::Float(((*lh_f as i64) % rh_i) as f64)
|
||||
}
|
||||
OwnedValue::Integer(lh_i) => OwnedValue::Integer(lh_i % rh_i),
|
||||
_ => {
|
||||
todo!("{:?}", aggctx);
|
||||
}
|
||||
},
|
||||
OwnedValue::Float(rh_f) => match aggctx.final_value() {
|
||||
OwnedValue::Null => OwnedValue::Null,
|
||||
OwnedValue::Float(lh_f) => {
|
||||
OwnedValue::Float(((*lh_f as i64) % (*rh_f as i64)) as f64)
|
||||
}
|
||||
OwnedValue::Integer(lh_i) => {
|
||||
OwnedValue::Float((lh_i % (*rh_f as i64)) as f64)
|
||||
}
|
||||
_ => {
|
||||
todo!("{:?}", aggctx);
|
||||
}
|
||||
},
|
||||
_ => todo!("{:?}", rhs),
|
||||
},
|
||||
_ => todo!("{:?} {:?}", state.registers[lhs], state.registers[rhs]),
|
||||
};
|
||||
state.pc += 1;
|
||||
}
|
||||
Insn::Null { dest, dest_end } => {
|
||||
if let Some(dest_end) = dest_end {
|
||||
for i in *dest..=*dest_end {
|
||||
|
||||
@@ -1025,3 +1025,51 @@ do_execsql_test log-null-int {
|
||||
do_execsql_test log-int-null {
|
||||
SELECT log(5, null)
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-int-null {
|
||||
SELECT 183 % null
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-int-0 {
|
||||
SELECT 183 % 0
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-int-int {
|
||||
SELECT 183 % 10
|
||||
} { 3 }
|
||||
|
||||
do_execsql_test mod-int-float {
|
||||
SELECT 38 % 10.35
|
||||
} { 8.0 }
|
||||
|
||||
do_execsql_test mod-float-int {
|
||||
SELECT 38.43 % 13
|
||||
} { 12.0 }
|
||||
|
||||
do_execsql_test mod-0-float {
|
||||
SELECT 0 % 12.0
|
||||
} { 0.0 }
|
||||
|
||||
do_execsql_test mod-float-0 {
|
||||
SELECT 23.14 % 0
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-float-float {
|
||||
SELECT 23.14 % 12.0
|
||||
} { 11.0 }
|
||||
|
||||
do_execsql_test mod-float-agg {
|
||||
SELECT 23.14 % sum(id) from products
|
||||
} { 23.0 }
|
||||
|
||||
do_execsql_test mod-int-agg {
|
||||
SELECT 17 % sum(id) from users
|
||||
} { 17 }
|
||||
|
||||
do_execsql_test mod-agg-int {
|
||||
SELECT count(*) % 17 from users
|
||||
} { 4 }
|
||||
|
||||
do_execsql_test mod-agg-float {
|
||||
SELECT count(*) % 2.43 from users
|
||||
} { 0.0 }
|
||||
|
||||
Reference in New Issue
Block a user