mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-09 02:04:22 +01:00
Implement ShiftRight
This commit is contained in:
@@ -446,7 +446,7 @@ Feature support of [sqlite expr syntax](https://www.sqlite.org/lang_expr.html).
|
||||
| Sequence | No |
|
||||
| SetCookie | No |
|
||||
| ShiftLeft | Yes |
|
||||
| ShiftRight | No |
|
||||
| ShiftRight | Yes |
|
||||
| SoftNull | Yes |
|
||||
| Sort | No |
|
||||
| SorterCompare | No |
|
||||
|
||||
@@ -613,6 +613,13 @@ pub fn translate_expr(
|
||||
dest: target_register,
|
||||
});
|
||||
}
|
||||
ast::Operator::RightShift => {
|
||||
program.emit_insn(Insn::ShiftRight {
|
||||
lhs: e1_reg,
|
||||
rhs: e2_reg,
|
||||
dest: target_register,
|
||||
});
|
||||
}
|
||||
ast::Operator::LeftShift => {
|
||||
program.emit_insn(Insn::ShiftLeft {
|
||||
lhs: e1_reg,
|
||||
|
||||
@@ -1044,6 +1044,15 @@ pub fn insn_to_str(
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
Insn::ShiftRight { lhs, rhs, dest } => (
|
||||
"ShiftRight",
|
||||
*rhs as i32,
|
||||
*lhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=r[{}] >> r[{}]", dest, lhs, rhs),
|
||||
),
|
||||
Insn::ShiftLeft { lhs, rhs, dest } => (
|
||||
"ShiftLeft",
|
||||
*rhs as i32,
|
||||
|
||||
@@ -488,6 +488,12 @@ pub enum Insn {
|
||||
where_clause: String,
|
||||
},
|
||||
// Place the result of lhs >> rhs in dest register.
|
||||
ShiftRight {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Place the result of lhs << rhs in dest register.
|
||||
ShiftLeft {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
@@ -774,3 +780,51 @@ fn compute_shl(lhs: i64, rhs: i64) -> i64 {
|
||||
lhs << rhs
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exec_shift_right(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
if let OwnedValue::Agg(agg) = lhs {
|
||||
lhs = agg.final_value();
|
||||
}
|
||||
if let OwnedValue::Agg(agg) = rhs {
|
||||
rhs = agg.final_value();
|
||||
}
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
|
||||
(OwnedValue::Integer(lh), OwnedValue::Integer(rh)) => {
|
||||
OwnedValue::Integer(compute_shr(*lh, *rh))
|
||||
}
|
||||
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => {
|
||||
OwnedValue::Integer(compute_shr(*lh as i64, *rh))
|
||||
}
|
||||
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => {
|
||||
OwnedValue::Integer(compute_shr(*lh, *rh as i64))
|
||||
}
|
||||
(OwnedValue::Float(lh), OwnedValue::Float(rh)) => {
|
||||
OwnedValue::Integer(compute_shr(*lh as i64, *rh as i64))
|
||||
}
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_shift_right(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
),
|
||||
(OwnedValue::Text(text), other) => {
|
||||
exec_shift_right(&cast_text_to_numerical(&text.value), other)
|
||||
}
|
||||
(other, OwnedValue::Text(text)) => {
|
||||
exec_shift_right(other, &cast_text_to_numerical(&text.value))
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_shr(lhs: i64, rhs: i64) -> i64 {
|
||||
if rhs == 0 {
|
||||
lhs
|
||||
} else if rhs >= 64 || rhs <= -64 {
|
||||
0
|
||||
} else if rhs < 0 {
|
||||
// if negative do left shift
|
||||
lhs << (-rhs)
|
||||
} else {
|
||||
lhs >> rhs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ use crate::{resolve_ext_path, Connection, Result, Rows, TransactionState, DATABA
|
||||
use datetime::{exec_date, exec_datetime_full, exec_julianday, exec_time, exec_unixepoch};
|
||||
use insn::{
|
||||
exec_add, exec_bit_and, exec_bit_not, exec_bit_or, exec_divide, exec_multiply, exec_remainder,
|
||||
exec_shift_left, exec_subtract,
|
||||
exec_shift_left, exec_shift_right, exec_subtract,
|
||||
};
|
||||
use likeop::{construct_like_escape_arg, exec_glob, exec_like_with_escape};
|
||||
use rand::distributions::{Distribution, Uniform};
|
||||
@@ -2158,6 +2158,11 @@ impl Program {
|
||||
parse_schema_rows(Some(rows), &mut schema, conn.pager.io.clone())?;
|
||||
state.pc += 1;
|
||||
}
|
||||
Insn::ShiftRight { lhs, rhs, dest } => {
|
||||
state.registers[*dest] =
|
||||
exec_shift_right(&state.registers[*lhs], &state.registers[*rhs]);
|
||||
state.pc += 1;
|
||||
}
|
||||
Insn::ShiftLeft { lhs, rhs, dest } => {
|
||||
state.registers[*dest] =
|
||||
exec_shift_left(&state.registers[*lhs], &state.registers[*rhs]);
|
||||
|
||||
@@ -515,6 +515,62 @@ foreach {testname lhs rhs ans} {
|
||||
do_execsql_test shift-left-$testname "SELECT $lhs << $rhs" $::ans
|
||||
}
|
||||
|
||||
foreach {testname lhs rhs ans} {
|
||||
int-int 8 2 2
|
||||
int-neg_int 8 -2 32
|
||||
int-float 8 1.0 4
|
||||
int-text 8 'a' 8
|
||||
int-text_float 8 '3.0' 1
|
||||
int-text_int 8 '1' 4
|
||||
int-null 8 NULL {}
|
||||
int-int-overflow 8 64 0
|
||||
int-int-underflow 8 -64 0
|
||||
int-float-overflow 8 64.0 0
|
||||
int-float-underflow 8 -64.0 0
|
||||
} {
|
||||
do_execsql_test shift-right-$testname "SELECT $lhs >> $rhs" $::ans
|
||||
}
|
||||
|
||||
foreach {testname lhs rhs ans} {
|
||||
float-int 8.0 2 2
|
||||
float-neg_int 8.0 -2 32
|
||||
float-float 8.0 1.0 4
|
||||
float-text 8.0 'a' 8
|
||||
float-text_float 8.0 '3.0' 1
|
||||
float-text_int 8.0 '1' 4
|
||||
float-null 8.0 NULL {}
|
||||
float-int-overflow 8.0 64 0
|
||||
float-int-underflow 8.0 -64 0
|
||||
float-float-overflow 8.0 64.0 0
|
||||
float-float-underflow 8.0 -64.0 0
|
||||
} {
|
||||
do_execsql_test shift-right-$testname "SELECT $lhs >> $rhs" $::ans
|
||||
}
|
||||
|
||||
foreach {testname lhs rhs ans} {
|
||||
text-int 'a' 2 0
|
||||
text-float 'a' 4.0 0
|
||||
text-text 'a' 'a' 0
|
||||
text_int-text_int '8' '1' 4
|
||||
text_int-text_float '8' '3.0' 1
|
||||
text_int-text '8' 'a' 8
|
||||
text_float-text_int '8.0' '1' 4
|
||||
text_float-text_float '8.0' '3.0' 1
|
||||
text_float-text '8.0' 'a' 8
|
||||
text-null '8' NULL {}
|
||||
} {
|
||||
do_execsql_test shift-right-$testname "SELECT $lhs >> $rhs" $::ans
|
||||
}
|
||||
|
||||
foreach {testname lhs rhs ans} {
|
||||
null-int NULL 2 {}
|
||||
null-float NULL 4.0 {}
|
||||
null-text NULL 'a' {}
|
||||
null-null NULL NULL {}
|
||||
} {
|
||||
do_execsql_test shift-right-$testname "SELECT $lhs >> $rhs" $::ans
|
||||
}
|
||||
|
||||
do_execsql_test bitwise-not-null {
|
||||
SELECT ~NULL
|
||||
} {}
|
||||
|
||||
Reference in New Issue
Block a user