Merge 'Pass input string to translate function' from Pedro Muniz

In preparation for `CREATE VIEW`, we need to have the original sql query
that was used to create the view. I'm using the scanner's offset to
slice into the original input, trimming the newlines, and passing it to
the translate function.

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #1621
This commit is contained in:
Jussi Saurio
2025-06-02 17:43:11 +03:00
2 changed files with 36 additions and 3 deletions

View File

@@ -33,6 +33,7 @@ mod numeric;
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
use crate::{fast_lock::SpinLock, translate::optimizer::optimize_plan};
use core::str;
pub use error::LimboError;
use fallible_iterator::FallibleIterator;
pub use io::clock::{Clock, Instant};
@@ -354,6 +355,10 @@ impl Connection {
let cmd = parser.next()?;
let syms = self.syms.borrow();
let cmd = cmd.expect("Successful parse on nonempty input string should produce a command");
let byte_offset_end = parser.offset();
let input = str::from_utf8(&sql.as_bytes()[..byte_offset_end])
.unwrap()
.trim();
match cmd {
Cmd::Stmt(stmt) => {
let program = Rc::new(translate::translate(
@@ -367,6 +372,7 @@ impl Connection {
Rc::downgrade(self),
&syms,
QueryMode::Normal,
&input,
)?);
Ok(Statement::new(
program,
@@ -385,14 +391,22 @@ impl Connection {
tracing::trace!("Querying: {}", sql);
let mut parser = Parser::new(sql.as_bytes());
let cmd = parser.next()?;
let byte_offset_end = parser.offset();
let input = str::from_utf8(&sql.as_bytes()[..byte_offset_end])
.unwrap()
.trim();
match cmd {
Some(cmd) => self.run_cmd(cmd),
Some(cmd) => self.run_cmd(cmd, input),
None => Ok(None),
}
}
#[instrument(skip_all, level = Level::TRACE)]
pub(crate) fn run_cmd(self: &Rc<Connection>, cmd: Cmd) -> Result<Option<Statement>> {
pub(crate) fn run_cmd(
self: &Rc<Connection>,
cmd: Cmd,
input: &str,
) -> Result<Option<Statement>> {
let syms = self.syms.borrow();
match cmd {
Cmd::Stmt(ref stmt) | Cmd::Explain(ref stmt) => {
@@ -407,6 +421,7 @@ impl Connection {
Rc::downgrade(self),
&syms,
cmd.into(),
input,
)?;
let stmt = Statement::new(
program.into(),
@@ -458,6 +473,10 @@ impl Connection {
let mut parser = Parser::new(sql.as_bytes());
let cmd = parser.next()?;
let syms = self.syms.borrow();
let byte_offset_end = parser.offset();
let input = str::from_utf8(&sql.as_bytes()[..byte_offset_end])
.unwrap()
.trim();
if let Some(cmd) = cmd {
match cmd {
Cmd::Explain(stmt) => {
@@ -472,6 +491,7 @@ impl Connection {
Rc::downgrade(self),
&syms,
QueryMode::Explain,
&input,
)?;
let _ = std::io::stdout().write_all(program.explain().as_bytes());
}
@@ -488,6 +508,7 @@ impl Connection {
Rc::downgrade(self),
&syms,
QueryMode::Normal,
&input,
)?;
let mut state =
@@ -1048,6 +1069,8 @@ impl SymbolTable {
pub struct QueryRunner<'a> {
parser: Parser<'a>,
conn: &'a Rc<Connection>,
statements: &'a [u8],
last_offset: usize,
}
impl<'a> QueryRunner<'a> {
@@ -1055,6 +1078,8 @@ impl<'a> QueryRunner<'a> {
Self {
parser: Parser::new(statements),
conn,
statements,
last_offset: 0,
}
}
}
@@ -1064,7 +1089,14 @@ impl Iterator for QueryRunner<'_> {
fn next(&mut self) -> Option<Self::Item> {
match self.parser.next() {
Ok(Some(cmd)) => Some(self.conn.run_cmd(cmd)),
Ok(Some(cmd)) => {
let byte_offset_end = self.parser.offset();
let input = str::from_utf8(&self.statements[self.last_offset..byte_offset_end])
.unwrap()
.trim();
self.last_offset = byte_offset_end;
Some(self.conn.run_cmd(cmd, &input))
}
Ok(None) => None,
Err(err) => {
self.parser.finalize();

View File

@@ -62,6 +62,7 @@ pub fn translate(
connection: Weak<Connection>,
syms: &SymbolTable,
query_mode: QueryMode,
_input: &str, // TODO: going to be used for CREATE VIEW
) -> Result<Program> {
let change_cnt_on = matches!(
stmt,