use std::{error::Error, fmt::Write, path::Path};
use reifydb_catalog::catalog::{Catalog, namespace::NamespaceToCreate, table::TableToCreate};
use reifydb_core::interface::catalog::{id::NamespaceId, namespace::Namespace};
use reifydb_engine::test_harness::create_test_admin_transaction;
use reifydb_rql::explain::{
ast::explain_ast, logical::explain_logical_plan, physical::explain_physical_plan, tokenize::explain_tokenize,
};
use reifydb_testing::testscript::{
command::Command,
runner::{Runner, run_path},
};
use reifydb_transaction::transaction::Transaction;
use reifydb_type::fragment::Fragment;
use test_each_file::test_each_path;
test_each_path! { in "crates/rql/tests/scripts/tokenize" as tokenize => run_test }
test_each_path! { in "crates/rql/tests/scripts/ast" as ast => run_test }
test_each_path! { in "crates/rql/tests/scripts/logical_plan" as logical_plan => run_test }
test_each_path! { in "crates/rql/tests/scripts/physical_plan" as physical_plan => run_test }
fn run_test(path: &Path) {
run_path(&mut TestRunner {}, path).expect("test failed")
}
pub struct TestRunner {}
impl Runner for TestRunner {
fn run(&mut self, command: &Command) -> Result<String, Box<dyn Error>> {
let mut output = String::new();
match command.name.as_str() {
"tokenize" => {
let mut args = command.consume_args();
let query = args.next_pos().ok_or("args not given")?.value.as_str();
args.reject_rest()?;
let result = explain_tokenize(query).unwrap();
writeln!(output, "{}", result).unwrap();
}
"ast" => {
let mut args = command.consume_args();
let query = args.next_pos().ok_or("args not given")?.value.as_str();
args.reject_rest()?;
let result = explain_ast(query).unwrap();
writeln!(output, "{}", result).unwrap();
}
"logical" => {
let mut args = command.consume_args();
let query = args.next_pos().ok_or("args not given")?.value.as_str();
args.reject_rest()?;
let rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(async {
let mut dummy_tx = create_test_admin_transaction();
let catalog = Catalog::testing();
let default_namespace = Namespace::default_namespace();
catalog.create_table(
&mut dummy_tx,
TableToCreate {
name: Fragment::internal("users"),
namespace: default_namespace.id(),
columns: vec![],
retention_strategy: None,
primary_key_columns: None,
underlying: false,
},
)
.unwrap();
catalog.create_table(
&mut dummy_tx,
TableToCreate {
name: Fragment::internal("orders"),
namespace: default_namespace.id(),
columns: vec![],
retention_strategy: None,
primary_key_columns: None,
underlying: false,
},
)
.unwrap();
let test_ns = catalog
.create_namespace(
&mut dummy_tx,
NamespaceToCreate {
namespace_fragment: None,
name: "test".to_string(),
local_name: "test".to_string(),
parent_id: NamespaceId::ROOT,
grpc: None,
token: None,
},
)
.unwrap();
catalog.create_table(
&mut dummy_tx,
TableToCreate {
name: Fragment::internal("users"),
namespace: test_ns.id(),
columns: vec![],
retention_strategy: None,
primary_key_columns: None,
underlying: false,
},
)
.unwrap();
explain_logical_plan(&catalog, &mut (&mut dummy_tx).into(), query).unwrap()
});
writeln!(output, "{}", result).unwrap();
}
"physical" => {
let mut args = command.consume_args();
let query = args.next_pos().ok_or("args not given")?.value.as_str();
args.reject_rest()?;
let rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(async {
let mut dummy_tx = create_test_admin_transaction();
let catalog = Catalog::testing();
let namespace = Namespace::default_namespace();
catalog.create_table(
&mut dummy_tx,
TableToCreate {
name: Fragment::internal("users"),
namespace: namespace.id(),
columns: vec![],
retention_strategy: None,
primary_key_columns: None,
underlying: false,
},
)
.unwrap();
catalog.create_table(
&mut dummy_tx,
TableToCreate {
name: Fragment::internal("orders"),
namespace: namespace.id(),
columns: vec![],
retention_strategy: None,
primary_key_columns: None,
underlying: false,
},
)
.unwrap();
explain_physical_plan(&catalog, &mut Transaction::Admin(&mut dummy_tx), query)
.unwrap()
});
writeln!(output, "{}", result).unwrap();
}
_ => unimplemented!(),
}
Ok(output)
}
}