#![warn(missing_docs)]
#![warn(clippy::all)]
#![deny(unsafe_code)]
pub mod connection;
pub mod dialect;
pub mod error;
pub mod pool;
pub mod schema;
pub mod security;
pub mod sink;
pub mod source;
pub mod types;
#[cfg(feature = "postgres")]
pub mod postgres;
#[cfg(feature = "mysql")]
pub mod mysql;
#[cfg(feature = "sqlserver")]
pub mod sqlserver;
pub mod prelude {
pub use crate::error::{Error, ErrorCategory, Result};
pub use crate::types::{ColumnMetadata, Row, TableMetadata, Value};
pub use crate::connection::{
Connection, ConnectionConfig, ConnectionFactory, ConnectionLifecycle, DatabaseType,
IsolationLevel, PreparedStatement, RowStream, Transaction,
};
pub use crate::pool::{
create_pool, create_pool_with_config, AtomicPoolStats, ConnectionPool, PoolBuilder,
PoolConfig, PoolStats, PooledConnection, RecycleReason, SimpleConnectionPool,
};
pub use crate::dialect::{
dialect_for, MariaDbDialect, MySqlDialect, PostgresDialect, SqlDialect, SqlServerDialect,
};
pub use crate::schema::{
AutoDdlMode, ForeignKeyAction, ForeignKeyMetadata, IdentityNaming, IndexMetadata,
PrefixNaming, SchemaEvolutionMode, SchemaEvolutionResult, SchemaManager, SchemaMapping,
SchemaProvider, SuffixNaming, TableNamingStrategy,
};
pub use crate::source::{
AtomicSourceStats, PollResult, QueryMode, SourceOffset, SourceQueryBuilder, SourceRecord,
SourceStats, TableSource, TableSourceConfig,
};
pub use crate::sink::{
AtomicSinkStats, BatchConfig, BatchResult, BufferedSink, FailedRecord, SinkRecord,
SinkStats, TableSink, TableSinkBuilder, TableSinkConfig, WriteMode,
};
}
pub use error::{Error, Result};
pub use types::Value;
#[cfg(test)]
mod tests {
use super::prelude::*;
#[test]
fn test_prelude_imports() {
let _value = Value::Int32(42);
let _config = ConnectionConfig::new("postgres://localhost/test");
let _batch = BatchConfig::default();
let _mode = WriteMode::Upsert;
}
#[test]
fn test_error_types() {
let err = Error::connection("test error");
assert!(err.is_retriable());
assert_eq!(err.category(), ErrorCategory::Connection);
}
#[test]
fn test_value_types() {
let v = Value::from(42_i32);
assert!(!v.is_null());
assert_eq!(v.as_i64(), Some(42));
let v = Value::from("hello");
assert_eq!(v.as_str(), Some("hello"));
}
#[test]
fn test_table_metadata() {
let mut table = TableMetadata::new("users");
table.schema = Some("public".into());
assert_eq!(table.qualified_name(), "public.users");
assert!(table.columns.is_empty());
}
#[test]
fn test_query_modes() {
assert!(!QueryMode::Bulk.is_incremental());
assert!(QueryMode::incrementing("id").is_incremental());
assert!(QueryMode::timestamp("updated_at").is_incremental());
}
#[test]
fn test_write_modes() {
assert_eq!(WriteMode::default(), WriteMode::Upsert);
}
#[test]
fn test_dialect_selection() {
let pg = dialect_for("postgres");
assert_eq!(pg.name(), "PostgreSQL");
let mysql = dialect_for("mysql");
assert_eq!(mysql.name(), "MySQL");
let mssql = dialect_for("sqlserver");
assert_eq!(mssql.name(), "SQL Server");
}
#[test]
fn test_source_config() {
let config = TableSourceConfig::incrementing("events", "id")
.with_schema("public")
.with_batch_size(500);
assert_eq!(config.table, "events");
assert_eq!(config.schema, Some("public".into()));
assert_eq!(config.batch_size, 500);
}
#[test]
fn test_sink_config() {
let config = TableSinkBuilder::new()
.batch_size(2000)
.write_mode(WriteMode::Insert)
.auto_ddl(AutoDdlMode::CreateAndEvolve)
.build();
assert_eq!(config.batch.max_size, 2000);
assert_eq!(config.write_mode, WriteMode::Insert);
assert_eq!(config.auto_ddl, AutoDdlMode::CreateAndEvolve);
}
}