diff --git a/src/parse/script/expr.rs b/src/parse/script/expr.rs index 8c17bbe8..bbe114d6 100644 --- a/src/parse/script/expr.rs +++ b/src/parse/script/expr.rs @@ -10,7 +10,7 @@ use crate::data::expr::{get_op, Expr}; use crate::data::functions::{OP_LIST, OP_MINUS, OP_NEGATE}; use crate::data::symb::Symbol; use crate::data::value::DataValue; -use crate::parse::script::{Pair, Pairs, Rule}; +use crate::parse::script::{Pair, Rule}; lazy_static! { static ref PREC_CLIMBER: PrecClimber = { diff --git a/src/parse/script/mod.rs b/src/parse/script/mod.rs index 98e1a59e..7eba4b62 100644 --- a/src/parse/script/mod.rs +++ b/src/parse/script/mod.rs @@ -9,6 +9,7 @@ use crate::parse::script::query::parse_query; pub(crate) mod query; pub(crate) mod expr; +pub(crate) mod pull; #[derive(pest_derive::Parser)] #[grammar = "cozoscript.pest"] diff --git a/src/parse/script/pull.rs b/src/parse/script/pull.rs new file mode 100644 index 00000000..7794d3dd --- /dev/null +++ b/src/parse/script/pull.rs @@ -0,0 +1,11 @@ +// fn parse_pull_spec(src: Pair<'_>) -> Result { +// let mut src = src.into_inner(); +// let name = src.next().unwrap().as_str(); +// let args: Vec<_> = src +// .next() +// .unwrap() +// .into_inner() +// .map(parse_pull_arg) +// .try_collect()?; +// Ok(json!({"pull": name, "spec": args})) +// } diff --git a/src/parse/script/query.rs b/src/parse/script/query.rs index 35057bdd..a26b0836 100644 --- a/src/parse/script/query.rs +++ b/src/parse/script/query.rs @@ -20,8 +20,8 @@ use crate::data::symb::{Symbol, PROG_ENTRY}; use crate::data::tuple::Tuple; use crate::data::value::DataValue; use crate::parse::query::{ConstRules, OutSpec, QueryOutOptions, SortDir, ViewOp}; -use crate::parse::script::{Pair, Pairs, Rule}; use crate::parse::script::expr::build_expr; +use crate::parse::script::{Pair, Pairs, Rule}; use crate::runtime::view::{ViewRelId, ViewRelKind, ViewRelMetadata}; pub(crate) fn parse_query( @@ -407,7 +407,10 @@ fn parse_algo_rule( let mut els = inner.into_inner(); let name = els.next().unwrap().as_str(); let args = els.map(|v| Symbol::from(v.as_str())).collect_vec(); - rule_args.push(AlgoRuleArg::Stored(Symbol::from(name), args)) + rule_args.push(AlgoRuleArg::Stored( + Symbol::from(name.strip_prefix(':').unwrap()), + args, + )) } Rule::algo_triple_rel => { let mut els = inner.into_inner(); @@ -449,13 +452,12 @@ fn parse_algo_rule( algo: AlgoHandle { name: Symbol::from(*algo_name), }, - rule_args: vec![], - options: Default::default(), + rule_args, + options, }, )) } - fn parse_limit_or_offset(src: Pair<'_>) -> Result { let src = src.into_inner().next().unwrap().as_str(); str2usize(src) diff --git a/src/runtime/db.rs b/src/runtime/db.rs index 5b2786b5..464ff641 100644 --- a/src/runtime/db.rs +++ b/src/runtime/db.rs @@ -6,10 +6,10 @@ use std::sync::{Arc, Mutex}; use std::time::Duration; use std::{fs, thread}; -use miette::{miette, bail, ensure, Result, IntoDiagnostic}; use either::{Left, Right}; use itertools::Itertools; use log::debug; +use miette::{bail, ensure, miette, IntoDiagnostic, Result}; use serde_json::json; use smartstring::SmartString; @@ -30,6 +30,7 @@ use crate::parse::cozoscript::query::{parse_query_to_json, ScriptType}; use crate::parse::cozoscript::sys::{CompactTarget, SysOp}; use crate::parse::query::ViewOp; use crate::parse::schema::AttrTxItem; +use crate::parse::script::{parse_script, CozoScript}; use crate::query::pull::CurrentPath; use crate::runtime::transact::SessionTx; use crate::runtime::view::{ViewRelId, ViewRelMetadata}; @@ -361,12 +362,12 @@ impl Db { Ok(json!(collected)) } pub fn run_script(&self, payload: &str) -> Result { - let (script_type, payload) = parse_query_to_json(payload)?; + let (script_type, json) = parse_query_to_json(payload)?; match script_type { ScriptType::Query => self.run_query(&payload), - ScriptType::Schema => self.transact_attributes(&payload), - ScriptType::Tx => self.transact_triples(&payload), - ScriptType::Sys => self.run_sys_op(payload), + ScriptType::Schema => self.transact_attributes(&json), + ScriptType::Tx => self.transact_triples(&json), + ScriptType::Sys => self.run_sys_op(json), } } pub fn convert_to_json_query(&self, payload: &str) -> Result { @@ -380,19 +381,20 @@ impl Db { Ok(json!({ key: payload })) } pub fn run_json_query(&self, payload: &JsonValue) -> Result { - let (k, v) = payload - .as_object() - .ok_or_else(|| miette!("json query must be an object"))? - .iter() - .next() - .ok_or_else(|| miette!("json query must be an object with keys"))?; - match k as &str { - "query" => self.run_query(v), - "schema" => self.transact_attributes(v), - "tx" => self.transact_triples(v), - "sys" => self.run_sys_op(v.clone()), - v => bail!("unexpected key in json query: {}", v), - } + todo!() + // let (k, v) = payload + // .as_object() + // .ok_or_else(|| miette!("json query must be an object"))? + // .iter() + // .next() + // .ok_or_else(|| miette!("json query must be an object with keys"))?; + // match k as &str { + // "query" => self.run_query(v), + // "schema" => self.transact_attributes(v), + // "tx" => self.transact_triples(v), + // "sys" => self.run_sys_op(v.clone()), + // v => bail!("unexpected key in json query: {}", v), + // } } pub fn run_sys_op(&self, payload: JsonValue) -> Result { let op: SysOp = serde_json::from_value(payload).into_diagnostic()?; @@ -433,9 +435,12 @@ impl Db { } } } - pub fn run_query(&self, payload: &JsonValue) -> Result { + pub fn run_query(&self, payload: &str) -> Result { let mut tx = self.transact()?; - let input_program = tx.parse_query(payload, &Default::default())?; + let input_program = match parse_script(payload, &Default::default())? { + CozoScript::Query(p) => p, + }; + // let input_program = tx.parse_query(payload, &Default::default())?; if let Some((meta, op)) = &input_program.out_opts.as_view { if *op == ViewOp::Create { ensure!( @@ -490,7 +495,8 @@ impl Db { }; if !input_program.out_opts.sorters.is_empty() { let entry_head = input_program.get_entry_head()?.to_vec(); - let sorted_result = tx.sort_and_collect(result, &input_program.out_opts.sorters, &entry_head)?; + let sorted_result = + tx.sort_and_collect(result, &input_program.out_opts.sorters, &entry_head)?; let sorted_iter = if let Some(offset) = input_program.out_opts.offset { Left(sorted_result.scan_sorted().skip(offset)) } else { diff --git a/tests/air_routes.rs b/tests/air_routes.rs index 4f34812d..44a8af47 100644 --- a/tests/air_routes.rs +++ b/tests/air_routes.rs @@ -25,86 +25,86 @@ fn init_logger() { fn air_routes() -> Result<()> { init_logger(); let db = create_db("_test_air_routes", false); - let attr_res = db.run_script( - r#" - :schema - - put country { - code: string identity, - desc: string - } - put continent { - code: string identity, - desc: string - } - put airport { - iata: string identity, - icao: string index, - city: string index, - desc: string, - region: string index, - country: ref, - runways: int, - longest: int, - altitude: int, - lat: float, - lon: float - } - put route { - src: ref, - dst: ref, - distance: int - } - put geo { - contains: ref many, - } - "#, - ); - - if attr_res.is_ok() { - let insertions = read_to_string("tests/air-routes-data.json").into_diagnostic()?; - let triple_insertion_time = Instant::now(); - db.run_script(&insertions)?; - dbg!(triple_insertion_time.elapsed()); - } - - let view_time = Instant::now(); - db.run_script(r#" - ?[?src, ?dst, ?distance] := [?r route.src ?src], [?r route.dst ?dst], [?r route.distance ?distance]; - :view rederive flies_to; - "#)?; - - dbg!(view_time.elapsed()); - - let view_time2 = Instant::now(); - db.run_script( - r#" - ?[?src_c, ?dst_c, ?distance] := [?r route.src ?src], [?r route.dst ?dst], - [?r route.distance ?distance], - [?src airport.iata ?src_c], [?dst airport.iata ?dst_c]; - :view rederive flies_to_code; - "#, - )?; - dbg!(view_time2.elapsed()); - - let view_time3 = Instant::now(); - db.run_script( - r#" - ?[?code, ?lat, ?lon] := [?n airport.iata ?code], [?n airport.lat ?lat], [?n airport.lon ?lon]; - :view rederive code_lat_lon; - "# - )?; - dbg!(view_time3.elapsed()); - - println!("views: {}", db.list_relations()?); - - let compact_main_time = Instant::now(); - db.compact_main()?; - dbg!(compact_main_time.elapsed()); - - let compact_view_time = Instant::now(); - db.compact_view()?; - dbg!(compact_view_time.elapsed()); + // let attr_res = db.run_script( + // r#" + // :schema + // + // put country { + // code: string identity, + // desc: string + // } + // put continent { + // code: string identity, + // desc: string + // } + // put airport { + // iata: string identity, + // icao: string index, + // city: string index, + // desc: string, + // region: string index, + // country: ref, + // runways: int, + // longest: int, + // altitude: int, + // lat: float, + // lon: float + // } + // put route { + // src: ref, + // dst: ref, + // distance: int + // } + // put geo { + // contains: ref many, + // } + // "#, + // ); + // + // if attr_res.is_ok() { + // let insertions = read_to_string("tests/air-routes-data.json").into_diagnostic()?; + // let triple_insertion_time = Instant::now(); + // db.run_script(&insertions)?; + // dbg!(triple_insertion_time.elapsed()); + // } + // + // let view_time = Instant::now(); + // db.run_script(r#" + // ?[?src, ?dst, ?distance] := [?r route.src ?src], [?r route.dst ?dst], [?r route.distance ?distance]; + // :view rederive flies_to; + // "#)?; + // + // dbg!(view_time.elapsed()); + // + // let view_time2 = Instant::now(); + // db.run_script( + // r#" + // ?[?src_c, ?dst_c, ?distance] := [?r route.src ?src], [?r route.dst ?dst], + // [?r route.distance ?distance], + // [?src airport.iata ?src_c], [?dst airport.iata ?dst_c]; + // :view rederive flies_to_code; + // "#, + // )?; + // dbg!(view_time2.elapsed()); + // + // let view_time3 = Instant::now(); + // db.run_script( + // r#" + // ?[?code, ?lat, ?lon] := [?n airport.iata ?code], [?n airport.lat ?lat], [?n airport.lon ?lon]; + // :view rederive code_lat_lon; + // "# + // )?; + // dbg!(view_time3.elapsed()); + // + // println!("views: {}", db.list_relations()?); + // + // let compact_main_time = Instant::now(); + // db.compact_main()?; + // dbg!(compact_main_time.elapsed()); + // + // let compact_view_time = Instant::now(); + // db.compact_view()?; + // dbg!(compact_view_time.elapsed()); let dfs_time = Instant::now(); let res = db.run_script(r#"