@ -10,6 +10,7 @@
use std ::collections ::BTreeMap ;
use std ::error ::Error ;
use std ::fs ;
use std ::fs ::File ;
use std ::io ::{ Read , Write } ;
@ -17,7 +18,7 @@ use clap::Args;
use miette ::{ bail , miette , IntoDiagnostic } ;
use serde_json ::{ json , Value } ;
use cozo ::{ DataValue , DbInstance };
use cozo ::{ DataValue , DbInstance , NamedRows };
struct Indented ;
@ -144,6 +145,58 @@ fn process_line(
if line . is_empty ( ) {
return Ok ( ( ) ) ;
}
let mut process_out = | out : NamedRows | -> miette ::Result < ( ) > {
if let Some ( path ) = save_next . as_ref ( ) {
println! (
"Query has returned {} rows, saving to file {}" ,
out . rows . len ( ) ,
path
) ;
let to_save = out
. rows
. iter ( )
. map ( | row | -> Value {
row . iter ( )
. zip ( out . headers . iter ( ) )
. map ( | ( v , k ) | ( k . to_string ( ) , v . clone ( ) ) )
. collect ( )
} )
. collect ( ) ;
let j_payload = Value ::Array ( to_save ) ;
let mut file = File ::create ( path ) . into_diagnostic ( ) ? ;
file . write_all ( j_payload . to_string ( ) . as_bytes ( ) )
. into_diagnostic ( ) ? ;
* save_next = None ;
} else {
use prettytable ::format ;
let mut table = prettytable ::Table ::new ( ) ;
let headers = out
. headers
. iter ( )
. map ( prettytable ::Cell ::from )
. collect ::< Vec < _ > > ( ) ;
table . set_titles ( prettytable ::Row ::new ( headers ) ) ;
let rows = out
. rows
. iter ( )
. map ( | r | r . iter ( ) . map ( | c | format! ( "{c}" ) ) . collect ::< Vec < _ > > ( ) )
. collect ::< Vec < _ > > ( ) ;
let rows = rows
. iter ( )
. map ( | r | r . iter ( ) . map ( prettytable ::Cell ::from ) . collect ::< Vec < _ > > ( ) ) ;
for row in rows {
table . add_row ( prettytable ::Row ::new ( row ) ) ;
}
table . set_format ( * format ::consts ::FORMAT_NO_BORDER_LINE_SEPARATOR ) ;
table . printstd ( ) ;
}
Ok ( ( ) )
} ;
if let Some ( remaining ) = line . strip_prefix ( '%' ) {
let remaining = remaining . trim ( ) ;
let ( op , payload ) = remaining
@ -179,6 +232,15 @@ fn process_line(
db . backup_db ( path ) ? ;
println! ( "Backup written successfully to {path}" )
}
"run" = > {
let path = payload . trim ( ) ;
if path . is_empty ( ) {
bail ! ( "Run requires path to a script" ) ;
}
let content = fs ::read_to_string ( path ) . into_diagnostic ( ) ? ;
let out = db . run_script ( & content , params . clone ( ) ) ? ;
process_out ( out ) ? ;
}
"restore" = > {
let path = payload . trim ( ) ;
if path . is_empty ( ) {
@ -216,53 +278,7 @@ fn process_line(
}
} else {
let out = db . run_script ( line , params . clone ( ) ) ? ;
if let Some ( path ) = save_next . as_ref ( ) {
println! (
"Query has returned {} rows, saving to file {}" ,
out . rows . len ( ) ,
path
) ;
let to_save = out
. rows
. iter ( )
. map ( | row | -> Value {
row . iter ( )
. zip ( out . headers . iter ( ) )
. map ( | ( v , k ) | ( k . to_string ( ) , v . clone ( ) ) )
. collect ( )
} )
. collect ( ) ;
let j_payload = Value ::Array ( to_save ) ;
let mut file = File ::create ( path ) . into_diagnostic ( ) ? ;
file . write_all ( j_payload . to_string ( ) . as_bytes ( ) )
. into_diagnostic ( ) ? ;
* save_next = None ;
} else {
use prettytable ::format ;
let mut table = prettytable ::Table ::new ( ) ;
let headers = out
. headers
. iter ( )
. map ( prettytable ::Cell ::from )
. collect ::< Vec < _ > > ( ) ;
table . set_titles ( prettytable ::Row ::new ( headers ) ) ;
let rows = out
. rows
. iter ( )
. map ( | r | r . iter ( ) . map ( | c | format! ( "{c}" ) ) . collect ::< Vec < _ > > ( ) )
. collect ::< Vec < _ > > ( ) ;
let rows = rows
. iter ( )
. map ( | r | r . iter ( ) . map ( prettytable ::Cell ::from ) . collect ::< Vec < _ > > ( ) ) ;
for row in rows {
table . add_row ( prettytable ::Row ::new ( row ) ) ;
}
table . set_format ( * format ::consts ::FORMAT_NO_BORDER_LINE_SEPARATOR ) ;
table . printstd ( ) ;
}
process_out ( out ) ? ;
}
Ok ( ( ) )
}