use std::sync::{Arc, RwLock};
use alopex_core::lsm::LsmKVConfig;
use alopex_core::lsm::wal::{SyncMode, WalConfig};
use alopex_core::{StorageFactory, StorageMode};
use crate::ast::expr::Literal;
use crate::catalog::{Catalog, ColumnMetadata, MemoryCatalog, TableMetadata};
use crate::executor::{ExecutionResult, Executor};
use crate::planner::typed_expr::{Projection, TypedAssignment, TypedExpr};
use crate::planner::types::ResolvedType;
use crate::{LogicalPlan, Span};
pub mod disk {
use super::*;
#[test]
fn ddl_and_dml_work_on_disk_mode_store() {
let dir = tempfile::tempdir().unwrap();
let cfg = LsmKVConfig {
wal: WalConfig {
segment_size: 4096,
max_segments: 2,
sync_mode: SyncMode::NoSync,
},
..Default::default()
};
let path = dir.path().to_path_buf();
let table = TableMetadata::new(
"users",
vec![
ColumnMetadata::new("id", ResolvedType::Integer)
.with_primary_key(true)
.with_not_null(true),
ColumnMetadata::new("name", ResolvedType::Text).with_not_null(true),
],
)
.with_primary_key(vec!["id".into()]);
let table_id = {
let store = Arc::new(
StorageFactory::create(StorageMode::Disk {
path: path.clone(),
config: Some(cfg.clone()),
})
.unwrap(),
);
let catalog = Arc::new(RwLock::new(MemoryCatalog::new()));
let mut executor = Executor::new(store, catalog.clone());
let res = executor
.execute(LogicalPlan::CreateTable {
table: table.clone(),
if_not_exists: false,
with_options: vec![],
})
.unwrap();
assert!(matches!(res, ExecutionResult::Success));
let values = vec![
vec![
TypedExpr::literal(
Literal::Number("1".into()),
ResolvedType::Integer,
Span::default(),
),
TypedExpr::literal(
Literal::String("a".into()),
ResolvedType::Text,
Span::default(),
),
],
vec![
TypedExpr::literal(
Literal::Number("2".into()),
ResolvedType::Integer,
Span::default(),
),
TypedExpr::literal(
Literal::String("b".into()),
ResolvedType::Text,
Span::default(),
),
],
];
let res = executor
.execute(LogicalPlan::Insert {
table: "users".into(),
columns: vec!["id".into(), "name".into()],
values,
})
.unwrap();
assert!(matches!(res, ExecutionResult::RowsAffected(2)));
let stored = catalog.read().unwrap().get_table("users").cloned().unwrap();
stored.table_id
};
let store = Arc::new(
StorageFactory::create(StorageMode::Disk {
path,
config: Some(cfg),
})
.unwrap(),
);
let catalog = Arc::new(RwLock::new(MemoryCatalog::new()));
{
let mut c = catalog.write().unwrap();
c.create_table(table.with_table_id(table_id)).unwrap();
}
let mut executor = Executor::new(store, catalog.clone());
let res = executor
.execute(LogicalPlan::Scan {
table: "users".into(),
projection: Projection::All(vec!["id".into(), "name".into()]),
})
.unwrap();
let ExecutionResult::Query(q) = res else {
panic!("expected query result");
};
assert_eq!(q.rows.len(), 2);
let assign = TypedAssignment {
column: "name".into(),
column_index: 1,
value: TypedExpr::literal(
Literal::String("z".into()),
ResolvedType::Text,
Span::default(),
),
};
let res = executor
.execute(LogicalPlan::Update {
table: "users".into(),
assignments: vec![assign],
filter: None,
})
.unwrap();
assert!(matches!(res, ExecutionResult::RowsAffected(2)));
let res = executor
.execute(LogicalPlan::Delete {
table: "users".into(),
filter: None,
})
.unwrap();
assert!(matches!(res, ExecutionResult::RowsAffected(2)));
let res = executor
.execute(LogicalPlan::Scan {
table: "users".into(),
projection: Projection::All(vec!["id".into(), "name".into()]),
})
.unwrap();
let ExecutionResult::Query(q) = res else {
panic!("expected query result");
};
assert_eq!(q.rows.len(), 0);
let res = executor
.execute(LogicalPlan::DropTable {
name: "users".into(),
if_exists: false,
})
.unwrap();
assert!(matches!(res, ExecutionResult::Success));
}
}