use tensorlogic_adapters::{
DomainInfo, MemoryDatabase, PredicateInfo, SchemaDatabase, SymbolTable,
};
#[cfg(feature = "sqlite")]
use tensorlogic_adapters::SQLiteDatabase;
#[cfg(feature = "postgres")]
use tensorlogic_adapters::PostgreSQLDatabase;
fn main() {
println!("=== TensorLogic Database Backends Demo ===\n");
demo_memory_database();
#[cfg(feature = "sqlite")]
demo_sqlite_database();
#[cfg(feature = "postgres")]
demo_postgres_database();
println!("\nDemo complete!");
}
fn demo_memory_database() {
println!("--- Memory Database Demo ---");
let mut db = MemoryDatabase::new();
let mut table = create_sample_schema();
let id = db
.store_schema("university_v1", &table)
.expect("Failed to store schema");
println!("Stored schema with ID: {:?}", id);
let loaded = db.load_schema(id).expect("Failed to load schema");
println!(
"Loaded schema with {} domains and {} predicates",
loaded.domains.len(),
loaded.predicates.len()
);
table
.add_domain(DomainInfo::new("Degree", 10))
.expect("Failed to add domain");
let id_v2 = db
.store_schema("university_v1", &table)
.expect("Failed to store v2");
println!("Stored version 2 with ID: {:?}", id_v2);
let schemas = db.list_schemas().expect("Failed to list schemas");
println!("Total schemas stored: {}", schemas.len());
for schema in &schemas {
println!(
" - {} (v{}): {} domains, {} predicates",
schema.name, schema.version, schema.num_domains, schema.num_predicates
);
}
let history = db
.get_schema_history("university_v1")
.expect("Failed to get history");
println!("Schema history ({} versions):", history.len());
for version in &history {
println!(
" - Version {}: created at {}",
version.version, version.timestamp
);
}
let results = db.search_schemas("university").expect("Failed to search");
println!("Search results for 'university': {} matches", results.len());
println!();
}
#[cfg(feature = "sqlite")]
fn demo_sqlite_database() {
println!("--- SQLite Database Demo ---");
use std::env::temp_dir;
let db_path = temp_dir().join("tensorlogic_example.db");
println!("Database path: {:?}", db_path);
let mut db = SQLiteDatabase::new(db_path.to_str().expect("unwrap"))
.expect("Failed to create SQLite database");
let table = create_sample_schema();
let id = db
.store_schema("persistent_schema", &table)
.expect("Failed to store schema");
println!("Stored schema with ID: {:?}", id);
let loaded = db.load_schema(id).expect("Failed to load schema");
println!(
"Loaded schema with {} domains and {} predicates",
loaded.domains.len(),
loaded.predicates.len()
);
println!("Schema is now persisted to disk at: {:?}", db_path);
println!("You can connect to it later using the same path");
let schemas = db.list_schemas().expect("Failed to list schemas");
println!("Schemas in database: {}", schemas.len());
for schema in &schemas {
println!(
" - {} (v{}): ID={:?}",
schema.name, schema.version, schema.id
);
}
std::fs::remove_file(&db_path).ok();
println!("Cleaned up temporary database file");
println!();
}
#[cfg(feature = "postgres")]
fn demo_postgres_database() {
println!("--- PostgreSQL Database Demo ---");
println!("Note: This demo requires a running PostgreSQL server");
println!("Connection string: host=localhost user=postgres password=postgres");
println!();
let runtime = tokio::runtime::Runtime::new().expect("Failed to create runtime");
runtime.block_on(async {
let connection_string = "host=localhost user=postgres password=postgres dbname=tensorlogic";
match PostgreSQLDatabase::new(connection_string).await {
Ok(mut db) => {
println!("Successfully connected to PostgreSQL");
let table = create_sample_schema();
let id = db
.store_schema_async("async_schema", &table)
.await
.expect("Failed to store schema");
println!("Stored schema with ID: {:?}", id);
let loaded = db
.load_schema_async(id)
.await
.expect("Failed to load schema");
println!(
"Loaded schema with {} domains and {} predicates",
loaded.domains.len(),
loaded.predicates.len()
);
let schemas = db
.list_schemas_async()
.await
.expect("Failed to list schemas");
println!("Schemas in database: {}", schemas.len());
for schema in &schemas {
println!(
" - {} (v{}): ID={:?}",
schema.name, schema.version, schema.id
);
}
println!();
}
Err(e) => {
println!("Failed to connect to PostgreSQL: {}", e);
println!("Make sure PostgreSQL is running and accessible");
println!("Example setup:");
println!(" docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres");
println!(" psql -h localhost -U postgres -c 'CREATE DATABASE tensorlogic;'");
println!();
}
}
});
}
fn create_sample_schema() -> SymbolTable {
let mut table = SymbolTable::new();
table
.add_domain(DomainInfo::new("Person", 100).with_description("People in the university"))
.expect("Failed to add Person domain");
table
.add_domain(DomainInfo::new("Course", 50).with_description("Available courses"))
.expect("Failed to add Course domain");
table
.add_domain(DomainInfo::new("Grade", 5).with_description("Grade values (A-F)"))
.expect("Failed to add Grade domain");
table
.add_predicate(
PredicateInfo::new("enrolled", vec!["Person".to_string(), "Course".to_string()])
.with_description("Person is enrolled in Course"),
)
.expect("Failed to add enrolled predicate");
table
.add_predicate(
PredicateInfo::new("teaches", vec!["Person".to_string(), "Course".to_string()])
.with_description("Person teaches Course"),
)
.expect("Failed to add teaches predicate");
table
.add_predicate(
PredicateInfo::new(
"grade",
vec![
"Person".to_string(),
"Course".to_string(),
"Grade".to_string(),
],
)
.with_description("Person received Grade in Course"),
)
.expect("Failed to add grade predicate");
table
.bind_variable("student", "Person")
.expect("Failed to bind student variable");
table
.bind_variable("professor", "Person")
.expect("Failed to bind professor variable");
table
.bind_variable("class", "Course")
.expect("Failed to bind class variable");
table
}