use crate::{
destinations::dialect::SqlDialect,
destinations::dialects::AnsiDialect,
error::{CdcError, Result},
types::Lsn,
};
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use pg_walstream::ChangeEvent;
use std::{collections::HashMap, future::Future, pin::Pin, sync::Arc};
pub type PreCommitHook =
Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = Result<()>> + Send>> + Send>;
pub type DestinationFactoryFn = Arc<dyn Fn() -> Result<Box<dyn DestinationHandler>> + Send + Sync>;
#[async_trait]
pub trait DestinationHandler: Send + Sync {
async fn connect(&mut self, connection_string: &str) -> Result<()>;
fn set_schema_mappings(&mut self, mappings: HashMap<String, String>);
fn set_max_rows_per_insert(&mut self, _max_rows: usize) {}
fn dialect(&self) -> &'static dyn SqlDialect {
static ANSI: AnsiDialect = AnsiDialect;
&ANSI
}
async fn execute_sql_batch_with_hook(
&mut self,
commands: &[String],
pre_commit_hook: Option<PreCommitHook>,
) -> Result<()>;
async fn close(&mut self) -> Result<()>;
fn supports_event_mode(&self) -> bool {
false
}
async fn execute_events_batch_with_hook(
&mut self,
_events: &[ChangeEvent],
_transaction_id: u32,
_commit_timestamp: DateTime<Utc>,
_commit_lsn: Option<Lsn>,
_pre_commit_hook: Option<PreCommitHook>,
) -> Result<()> {
Err(CdcError::unsupported(
"Event mode not supported by this destination",
))
}
fn supports_bulk_insert(&self) -> bool {
false
}
async fn execute_bulk_insert_with_hook(
&mut self,
table: &str,
columns: &[String],
rows: &[Vec<String>],
pre_commit_hook: Option<PreCommitHook>,
) -> Result<()> {
if rows.is_empty() {
return Ok(());
}
let sqls = crate::destinations::bulk_insert::build_chunked_multi_value_inserts(
table, columns, rows, None, None,
);
self.execute_sql_batch_with_hook(&sqls, pre_commit_hook)
.await
}
}