mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 10:08:20 +00:00
Better support for BLOBs
- Limbo command line shell supports e.g. `SELECT x'616263';` - `EXPLAIN SELECT x'616263';` lists the opcode Missing: - Command line shell not entirely compatible with SQLite when blobs have non-printable characters in the middle (e.g. `SELECT x'610062';`) - Python bindings not supported (incoming soon)
This commit is contained in:
parent
f23c668488
commit
0597c048fc
7 changed files with 67 additions and 12 deletions
|
@ -216,7 +216,7 @@ This document describes the SQLite compatibility status of Limbo:
|
|||
| BitAnd | No |
|
||||
| BitNot | No |
|
||||
| BitOr | No |
|
||||
| Blob | No |
|
||||
| Blob | Yes |
|
||||
| Checkpoint | No |
|
||||
| Clear | No |
|
||||
| Close | No |
|
||||
|
|
|
@ -275,7 +275,9 @@ fn query(
|
|||
Value::Integer(i) => print!("{}", i),
|
||||
Value::Float(f) => print!("{:?}", f),
|
||||
Value::Text(s) => print!("{}", s),
|
||||
Value::Blob(b) => print!("{:?}", b),
|
||||
Value::Blob(b) => {
|
||||
print!("{}", String::from_utf8_lossy(b))
|
||||
}
|
||||
}
|
||||
}
|
||||
println!();
|
||||
|
@ -305,7 +307,9 @@ fn query(
|
|||
Value::Integer(i) => i.to_string().cell(),
|
||||
Value::Float(f) => f.to_string().cell(),
|
||||
Value::Text(s) => s.cell(),
|
||||
Value::Blob(b) => format!("{:?}", b).cell(),
|
||||
Value::Blob(b) => {
|
||||
format!("{}", String::from_utf8_lossy(b)).cell()
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
|
|
|
@ -1433,7 +1433,23 @@ pub fn translate_expr(
|
|||
});
|
||||
Ok(target_register)
|
||||
}
|
||||
ast::Literal::Blob(_) => todo!(),
|
||||
ast::Literal::Blob(s) => {
|
||||
let bytes = s
|
||||
.as_bytes()
|
||||
.chunks_exact(2)
|
||||
.map(|pair| {
|
||||
// We assume that sqlite3-parser has already validated that
|
||||
// the input is valid hex string, thus unwrap is safe.
|
||||
let hex_byte = std::str::from_utf8(pair).unwrap();
|
||||
u8::from_str_radix(hex_byte, 16).unwrap()
|
||||
})
|
||||
.collect();
|
||||
program.emit_insn(Insn::Blob {
|
||||
value: bytes,
|
||||
dest: target_register,
|
||||
});
|
||||
Ok(target_register)
|
||||
}
|
||||
ast::Literal::Keyword(_) => todo!(),
|
||||
ast::Literal::Null => {
|
||||
program.emit_insn(Insn::Null {
|
||||
|
|
|
@ -470,6 +470,20 @@ pub fn insn_to_str(
|
|||
0,
|
||||
format!("r[{}]='{}'", dest, value),
|
||||
),
|
||||
Insn::Blob { value, dest } => (
|
||||
"Blob",
|
||||
0,
|
||||
*dest as i32,
|
||||
0,
|
||||
OwnedValue::Blob(Rc::new(value.clone())),
|
||||
0,
|
||||
format!(
|
||||
"r[{}]={} (len={})",
|
||||
dest,
|
||||
String::from_utf8_lossy(value),
|
||||
value.len()
|
||||
),
|
||||
),
|
||||
Insn::RowId { cursor_id, dest } => (
|
||||
"RowId",
|
||||
*cursor_id as i32,
|
||||
|
|
|
@ -279,6 +279,12 @@ pub enum Insn {
|
|||
dest: usize,
|
||||
},
|
||||
|
||||
// Write a blob value into a register.
|
||||
Blob {
|
||||
value: Vec<u8>,
|
||||
dest: usize,
|
||||
},
|
||||
|
||||
// Read the rowid of the current row.
|
||||
RowId {
|
||||
cursor_id: CursorID,
|
||||
|
@ -1074,6 +1080,10 @@ impl Program {
|
|||
state.registers[*dest] = OwnedValue::Text(Rc::new(value.into()));
|
||||
state.pc += 1;
|
||||
}
|
||||
Insn::Blob { value, dest } => {
|
||||
state.registers[*dest] = OwnedValue::Blob(Rc::new(value.clone()));
|
||||
state.pc += 1;
|
||||
}
|
||||
Insn::RowId { cursor_id, dest } => {
|
||||
let cursor = cursors.get_mut(cursor_id).unwrap();
|
||||
if let Some(ref rowid) = cursor.rowid()? {
|
||||
|
|
|
@ -395,14 +395,13 @@ do_execsql_test typeof-real {
|
|||
SELECT typeof(1.0);
|
||||
} {real}
|
||||
|
||||
# TODO: Uncomment when blobs are better supported
|
||||
# do_execsql_test typeof-blob {
|
||||
# SELECT typeof(x'61');
|
||||
# } {blob}
|
||||
#
|
||||
# do_execsql_test typeof-blob-empty {
|
||||
# SELECT typeof(x'');
|
||||
# } {blob}
|
||||
do_execsql_test typeof-blob {
|
||||
SELECT typeof(x'61');
|
||||
} {blob}
|
||||
|
||||
do_execsql_test typeof-blob-empty {
|
||||
SELECT typeof(x'');
|
||||
} {blob}
|
||||
|
||||
do_execsql_test typeof-sum-integer {
|
||||
SELECT typeof(sum(age)) from users;
|
||||
|
|
|
@ -11,6 +11,18 @@ do_execsql_test select-const-2 {
|
|||
SELECT 2
|
||||
} {2}
|
||||
|
||||
do_execsql_test select-blob-empty {
|
||||
SELECT x'';
|
||||
} {}
|
||||
|
||||
do_execsql_test select-blob-ascii {
|
||||
SELECT x'6C696D626f';
|
||||
} {limbo}
|
||||
|
||||
do_execsql_test select-blob-emoji {
|
||||
SELECT x'F09FA680';
|
||||
} {🦀}
|
||||
|
||||
do_execsql_test select-limit-0 {
|
||||
SELECT id FROM users LIMIT 0;
|
||||
} {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue