tx2_query/lib.rs
1//! tx2-query - SQL Analytics Layer for TX-2 ECS
2//!
3//! tx2-query provides a SQL side-car database for TX-2 applications, enabling
4//! advanced analytics, complex queries, and external tool integration while keeping
5//! the ECS world as the source of truth.
6//!
7//! # Architecture
8//!
9//! - **ECS World → SQL Database**: One-way synchronization from ECS to SQL
10//! - **Component → Table Mapping**: Automatic schema generation from component types
11//! - **Incremental Sync**: Track and sync only changed entities/components
12//! - **Multiple Backends**: PostgreSQL, SQLite, DuckDB, and more
13//!
14//! # Features
15//!
16//! - **Schema Generation**: Automatic DDL creation from component definitions
17//! - **Query Builder**: Ergonomic SQL query construction
18//! - **Sync API**: Incremental synchronization with batching and transactions
19//! - **Read-Only Projection**: Analytics layer, not an ORM
20//! - **Backend Abstraction**: Support for multiple SQL databases
21//!
22//! # Example
23//!
24//! ```rust,no_run
25//! use tx2_query::*;
26//! use tx2_query::schema::{SchemaGenerator, SqlType};
27//! use tx2_query::builder::SelectBuilder;
28//!
29//! #[derive(Debug)]
30//! struct Player;
31//!
32//! #[tokio::main]
33//! async fn main() -> Result<()> {
34//! // Create schema generator
35//! let mut schema_gen = SchemaGenerator::new();
36//! schema_gen.register::<Player>(
37//! "Player",
38//! vec![
39//! ("name", SqlType::Text, false),
40//! ("email", SqlType::Text, false),
41//! ("score", SqlType::Integer, false),
42//! ],
43//! )?;
44//!
45//! // Connect to database (requires postgres feature)
46//! #[cfg(feature = "postgres")]
47//! {
48//! use tx2_query::postgres::PostgresBackend;
49//! let backend = PostgresBackend::connect("postgresql://localhost/mydb").await?;
50//! let sync = tx2_query::sync::QuerySync::new(backend, schema_gen);
51//!
52//! // Initialize schema
53//! sync.initialize_schema().await?;
54//!
55//! // Build and execute queries
56//! let query = SelectBuilder::new("Player")
57//! .select(vec!["name", "score"])
58//! .where_gt("score", serde_json::json!(1000))
59//! .order_desc("score")
60//! .limit(10)
61//! .build()?;
62//!
63//! let results = sync.query(&query).await?;
64//! println!("Top players: {:?}", results);
65//! }
66//!
67//! Ok(())
68//! }
69//! ```
70//!
71//! # Backend Support
72//!
73//! Enable backends via Cargo features:
74//!
75//! ```toml
76//! [dependencies]
77//! tx2-query = { version = "0.1", features = ["postgres", "sqlite", "duckdb"] }
78//! ```
79//!
80//! # Philosophy
81//!
82//! tx2-query is designed as an analytics layer, NOT an ORM:
83//!
84//! - ECS world is always the source of truth
85//! - SQL database is a read-only projection for analytics
86//! - No bi-directional sync - changes flow ECS → SQL only
87//! - Optimized for analytical queries, not transactional workloads
88
89pub mod backend;
90pub mod builder;
91pub mod error;
92pub mod schema;
93pub mod sync;
94
95#[cfg(feature = "postgres")]
96pub mod postgres;
97
98#[cfg(feature = "sqlite")]
99pub mod sqlite;
100
101#[cfg(feature = "duckdb")]
102pub mod duckdb;
103
104pub use backend::{DatabaseBackend, QueryResult, QueryRow, Transaction};
105pub use builder::{
106 AggregateFunc, ComparisonOp, Condition, DeleteBuilder, JoinType, LogicalOp, SelectBuilder,
107 SortDirection, UpdateBuilder,
108};
109pub use error::{QueryError, Result};
110pub use schema::{ColumnDef, IndexDef, SchemaGenerator, SqlType, TableSchema};
111pub use sync::{ComponentChange, EntityChange, QuerySync, SyncBatch, SyncConfig};
112
113#[cfg(feature = "postgres")]
114pub use postgres::PostgresBackend;
115
116#[cfg(feature = "sqlite")]
117pub use sqlite::SqliteBackend;
118
119#[cfg(feature = "duckdb")]
120pub use duckdb::DuckDBBackend;
121
122/// Prelude for common imports
123pub mod prelude {
124 pub use crate::backend::{DatabaseBackend, QueryResult, QueryRow};
125 pub use crate::builder::{
126 ComparisonOp, Condition, SelectBuilder, SortDirection, UpdateBuilder,
127 };
128 pub use crate::error::{QueryError, Result};
129 pub use crate::schema::{SchemaGenerator, SqlType};
130 pub use crate::sync::{QuerySync, SyncConfig};
131
132 #[cfg(feature = "postgres")]
133 pub use crate::postgres::PostgresBackend;
134
135 #[cfg(feature = "sqlite")]
136 pub use crate::sqlite::SqliteBackend;
137
138 #[cfg(feature = "duckdb")]
139 pub use crate::duckdb::DuckDBBackend;
140}
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145
146 #[test]
147 fn test_library_exports() {
148 // Ensure all main types are exported
149 let _schema = SchemaGenerator::new();
150 let _sql_type = SqlType::Text;
151 let _comp_op = ComparisonOp::Eq;
152 let _log_op = LogicalOp::And;
153 }
154}