mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-23 00:45:37 +01:00
Run all statements from sql argument in cli
This commit is contained in:
41
cli/app.rs
41
cli/app.rs
@@ -3,7 +3,7 @@ use crate::{
|
||||
opcodes_dictionary::OPCODE_DESCRIPTIONS,
|
||||
};
|
||||
use cli_table::{Cell, Table};
|
||||
use limbo_core::{Database, LimboError, StepResult, Value};
|
||||
use limbo_core::{Database, LimboError, Rows, StepResult, Value};
|
||||
|
||||
use clap::{Parser, ValueEnum};
|
||||
use std::{
|
||||
@@ -304,8 +304,14 @@ impl Limbo {
|
||||
fn handle_first_input(&mut self, cmd: &str) {
|
||||
if cmd.trim().starts_with('.') {
|
||||
self.handle_dot_command(cmd);
|
||||
} else if let Err(e) = self.query(cmd) {
|
||||
eprintln!("{}", e);
|
||||
} else {
|
||||
let conn = self.conn.clone();
|
||||
let runner = conn.query_runner(cmd.as_bytes());
|
||||
for output in runner {
|
||||
if let Err(e) = self.print_query_result(cmd, output) {
|
||||
let _ = self.writeln(e.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
std::process::exit(0);
|
||||
}
|
||||
@@ -443,17 +449,16 @@ impl Limbo {
|
||||
self.buffer_input(line);
|
||||
let buff = self.input_buff.clone();
|
||||
let echo = self.opts.echo;
|
||||
buff.split(';')
|
||||
.map(str::trim)
|
||||
.filter(|s| !s.is_empty())
|
||||
.for_each(|stmt| {
|
||||
if echo {
|
||||
let _ = self.writeln(stmt);
|
||||
}
|
||||
if let Err(e) = self.query(stmt) {
|
||||
let _ = self.writeln(e.to_string());
|
||||
}
|
||||
});
|
||||
if echo {
|
||||
let _ = self.writeln(&buff);
|
||||
}
|
||||
let conn = self.conn.clone();
|
||||
let runner = conn.query_runner(buff.as_bytes());
|
||||
for output in runner {
|
||||
if let Err(e) = self.print_query_result(&buff, output) {
|
||||
let _ = self.writeln(e.to_string());
|
||||
}
|
||||
}
|
||||
self.reset_input();
|
||||
} else {
|
||||
self.buffer_input(line);
|
||||
@@ -570,8 +575,12 @@ impl Limbo {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn query(&mut self, sql: &str) -> anyhow::Result<()> {
|
||||
match self.conn.query(sql) {
|
||||
fn print_query_result(
|
||||
&mut self,
|
||||
sql: &str,
|
||||
mut output: Result<Option<Rows>, LimboError>,
|
||||
) -> anyhow::Result<()> {
|
||||
match output {
|
||||
Ok(Some(ref mut rows)) => match self.opts.output_mode {
|
||||
OutputMode::Raw => loop {
|
||||
if self.interrupt_count.load(Ordering::SeqCst) > 0 {
|
||||
|
||||
126
core/lib.rs
126
core/lib.rs
@@ -298,57 +298,65 @@ impl Connection {
|
||||
pub fn query(self: &Rc<Connection>, sql: impl Into<String>) -> Result<Option<Rows>> {
|
||||
let sql = sql.into();
|
||||
trace!("Querying: {}", sql);
|
||||
let db = self.db.clone();
|
||||
let syms: &SymbolTable = &db.syms.borrow();
|
||||
let mut parser = Parser::new(sql.as_bytes());
|
||||
let cmd = parser.next()?;
|
||||
if let Some(cmd) = cmd {
|
||||
match cmd {
|
||||
Cmd::Stmt(stmt) => {
|
||||
let program = Rc::new(translate::translate(
|
||||
&self.schema.borrow(),
|
||||
stmt,
|
||||
self.header.clone(),
|
||||
self.pager.clone(),
|
||||
Rc::downgrade(self),
|
||||
syms,
|
||||
)?);
|
||||
let stmt = Statement::new(program, self.pager.clone());
|
||||
Ok(Some(Rows { stmt }))
|
||||
}
|
||||
Cmd::Explain(stmt) => {
|
||||
let program = translate::translate(
|
||||
&self.schema.borrow(),
|
||||
stmt,
|
||||
self.header.clone(),
|
||||
self.pager.clone(),
|
||||
Rc::downgrade(self),
|
||||
syms,
|
||||
)?;
|
||||
program.explain();
|
||||
Ok(None)
|
||||
}
|
||||
Cmd::ExplainQueryPlan(stmt) => {
|
||||
match stmt {
|
||||
ast::Stmt::Select(select) => {
|
||||
let mut plan = prepare_select_plan(
|
||||
&self.schema.borrow(),
|
||||
*select,
|
||||
&self.db.syms.borrow(),
|
||||
)?;
|
||||
optimize_plan(&mut plan)?;
|
||||
println!("{}", plan);
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
match cmd {
|
||||
Some(cmd) => self.run_cmd(cmd),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn run_cmd(self: &Rc<Connection>, cmd: Cmd) -> Result<Option<Rows>> {
|
||||
let db = self.db.clone();
|
||||
let syms: &SymbolTable = &db.syms.borrow();
|
||||
|
||||
match cmd {
|
||||
Cmd::Stmt(stmt) => {
|
||||
let program = Rc::new(translate::translate(
|
||||
&self.schema.borrow(),
|
||||
stmt,
|
||||
self.header.clone(),
|
||||
self.pager.clone(),
|
||||
Rc::downgrade(self),
|
||||
syms,
|
||||
)?);
|
||||
let stmt = Statement::new(program, self.pager.clone());
|
||||
Ok(Some(Rows { stmt }))
|
||||
}
|
||||
Cmd::Explain(stmt) => {
|
||||
let program = translate::translate(
|
||||
&self.schema.borrow(),
|
||||
stmt,
|
||||
self.header.clone(),
|
||||
self.pager.clone(),
|
||||
Rc::downgrade(self),
|
||||
syms,
|
||||
)?;
|
||||
program.explain();
|
||||
Ok(None)
|
||||
}
|
||||
Cmd::ExplainQueryPlan(stmt) => {
|
||||
match stmt {
|
||||
ast::Stmt::Select(select) => {
|
||||
let mut plan = prepare_select_plan(
|
||||
&self.schema.borrow(),
|
||||
*select,
|
||||
&self.db.syms.borrow(),
|
||||
)?;
|
||||
optimize_plan(&mut plan)?;
|
||||
println!("{}", plan);
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn query_runner<'a>(self: &'a Rc<Connection>, sql: &'a [u8]) -> QueryRunner<'a> {
|
||||
QueryRunner::new(self, sql)
|
||||
}
|
||||
|
||||
pub fn execute(self: &Rc<Connection>, sql: impl Into<String>) -> Result<()> {
|
||||
let sql = sql.into();
|
||||
let db = self.db.clone();
|
||||
@@ -560,3 +568,29 @@ impl SymbolTable {
|
||||
self.functions.get(name).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct QueryRunner<'a> {
|
||||
parser: Parser<'a>,
|
||||
conn: &'a Rc<Connection>,
|
||||
}
|
||||
|
||||
impl<'a> QueryRunner<'a> {
|
||||
pub(crate) fn new(conn: &'a Rc<Connection>, statements: &'a [u8]) -> Self {
|
||||
Self {
|
||||
parser: Parser::new(statements),
|
||||
conn,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for QueryRunner<'_> {
|
||||
type Item = Result<Option<Rows>>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.parser.next() {
|
||||
Ok(Some(cmd)) => Some(self.conn.run_cmd(cmd)),
|
||||
Ok(None) => None,
|
||||
Err(err) => Some(Result::Err(LimboError::from(err))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
#!/usr/bin/env tclsh
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} basic-insert {
|
||||
create table temp (t1 integer, primary key (t1));
|
||||
insert into temp values (1);
|
||||
select * from temp;
|
||||
} {1}
|
||||
Reference in New Issue
Block a user