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, 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"] }
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
101pub use backend::{DatabaseBackend, QueryResult, QueryRow, Transaction};
102pub use builder::{
103 AggregateFunc, ComparisonOp, Condition, DeleteBuilder, JoinType, LogicalOp, SelectBuilder,
104 SortDirection, UpdateBuilder,
105};
106pub use error::{QueryError, Result};
107pub use schema::{ColumnDef, IndexDef, SchemaGenerator, SqlType, TableSchema};
108pub use sync::{ComponentChange, EntityChange, QuerySync, SyncBatch, SyncConfig};
109
110#[cfg(feature = "postgres")]
111pub use postgres::PostgresBackend;
112
113#[cfg(feature = "sqlite")]
114pub use sqlite::SqliteBackend;
115
116/// Prelude for common imports
117pub mod prelude {
118 pub use crate::backend::{DatabaseBackend, QueryResult, QueryRow};
119 pub use crate::builder::{
120 ComparisonOp, Condition, SelectBuilder, SortDirection, UpdateBuilder,
121 };
122 pub use crate::error::{QueryError, Result};
123 pub use crate::schema::{SchemaGenerator, SqlType};
124 pub use crate::sync::{QuerySync, SyncConfig};
125
126 #[cfg(feature = "postgres")]
127 pub use crate::postgres::PostgresBackend;
128
129 #[cfg(feature = "sqlite")]
130 pub use crate::sqlite::SqliteBackend;
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_library_exports() {
139 // Ensure all main types are exported
140 let _schema = SchemaGenerator::new();
141 let _sql_type = SqlType::Text;
142 let _comp_op = ComparisonOp::Eq;
143 let _log_op = LogicalOp::And;
144 }
145}