Skip to main content

bsql_core/
lib.rs

1#![forbid(unsafe_code)]
2
3//! Runtime support for bsql.
4//!
5//! This crate provides the types that `bsql::query!` generated code depends on:
6//! error types, connection pool, and the executor trait.
7//!
8//! You should not depend on this crate directly — use [`bsql`] instead.
9
10pub mod error;
11pub mod executor;
12pub mod listener;
13pub mod pool;
14pub mod singleflight;
15#[cfg(feature = "sqlite")]
16pub mod sqlite_pool;
17pub mod stream;
18pub mod transaction;
19pub mod types;
20pub mod util;
21
22/// Re-export bsql_driver_postgres types used by generated code.
23/// Users do not need to depend on bsql-driver directly.
24pub mod driver {
25    pub use bsql_driver_postgres::arena::{acquire_arena, release_arena};
26    pub use bsql_driver_postgres::hash_sql;
27    pub use bsql_driver_postgres::{Arena, Encode, PgDataRow, QueryResult, Row};
28
29    // Scalar decode functions for generated inline raw-bytes code
30    pub use bsql_driver_postgres::codec::decode_str;
31
32    // Array decode functions for generated code
33    pub use bsql_driver_postgres::codec::{
34        decode_array_bool, decode_array_bytea, decode_array_f32, decode_array_f64,
35        decode_array_i16, decode_array_i32, decode_array_i64, decode_array_str,
36    };
37
38    // Feature-gated decode functions for generated code
39    #[cfg(feature = "decimal")]
40    pub use bsql_driver_postgres::codec::decode_numeric_decimal;
41    #[cfg(feature = "uuid")]
42    pub use bsql_driver_postgres::codec::decode_uuid_type;
43    #[cfg(feature = "chrono")]
44    pub use bsql_driver_postgres::codec::{
45        decode_date_chrono, decode_time_chrono, decode_timestamptz_chrono,
46    };
47    #[cfg(feature = "time")]
48    pub use bsql_driver_postgres::codec::{
49        decode_date_time, decode_time_time, decode_timestamptz_time,
50    };
51}
52
53/// Re-export bsql_driver_sqlite types used by generated SQLite code.
54#[cfg(feature = "sqlite")]
55pub mod driver_sqlite {
56    pub use bsql_driver_sqlite::SqliteError;
57    pub use bsql_driver_sqlite::codec::SqliteEncode;
58    pub use bsql_driver_sqlite::conn::SqliteConnection;
59    pub use bsql_driver_sqlite::ffi::{StepResult, StmtHandle};
60    pub use bsql_driver_sqlite::pool::ParamValue;
61    pub use smallvec::{SmallVec, smallvec};
62
63    // Arena types for arena-backed fetch_all
64    pub use bsql_arena::{Arena, ArenaRows, ValidatedRows, acquire_arena};
65
66    /// SQLite NULL type indicator (matches `SQLITE_NULL` = 5).
67    /// Re-exported here so generated code does not need a direct libsqlite3-sys dep.
68    pub const SQLITE_NULL: i32 = 5;
69}
70
71pub use error::{BsqlError, BsqlResult};
72pub use executor::{Executor, OwnedResult};
73pub use listener::{Listener, Notification};
74pub use pool::{Pool, PoolBuilder, PoolConnection, PoolStatus};
75#[cfg(feature = "sqlite")]
76pub use sqlite_pool::{SqlitePool, SqliteStreamingQuery, SqliteTransaction};
77pub use stream::QueryStream;
78pub use transaction::{IsolationLevel, Transaction};
79
80/// Hash a string using rapidhash. Used by singleflight, statement naming,
81/// and offline cache keys. Not part of the public API.
82#[doc(hidden)]
83pub fn rapid_hash_str(s: &str) -> u64 {
84    use std::hash::{Hash, Hasher};
85    let mut hasher = rapidhash::quality::RapidHasher::default();
86    s.hash(&mut hasher);
87    hasher.finish()
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn rapid_hash_str_deterministic() {
96        let h1 = rapid_hash_str("SELECT 1");
97        let h2 = rapid_hash_str("SELECT 1");
98        assert_eq!(h1, h2);
99    }
100
101    #[test]
102    fn rapid_hash_str_different_inputs_differ() {
103        let h1 = rapid_hash_str("SELECT 1");
104        let h2 = rapid_hash_str("SELECT 2");
105        assert_ne!(h1, h2);
106    }
107
108    #[test]
109    fn rapid_hash_str_empty_string() {
110        let h = rapid_hash_str("");
111        // Should not panic, and the hash should be consistent
112        assert_eq!(h, rapid_hash_str(""));
113    }
114}