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}