use serde::{Deserialize, Serialize};
use crate::PgLsn;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SourceMetadata {
pub database: String,
pub slot: String,
pub publication: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ReplicaIdentity {
Default,
Nothing,
Full,
Index,
Unknown(u8),
}
impl ReplicaIdentity {
#[must_use]
pub fn from_wire(value: u8) -> Self {
match value {
b'd' => Self::Default,
b'n' => Self::Nothing,
b'f' => Self::Full,
b'i' => Self::Index,
other => Self::Unknown(other),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ColumnMetadata {
pub name: String,
pub type_oid: u32,
pub type_modifier: i32,
pub key: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RelationMetadata {
pub oid: u32,
pub schema: String,
pub table: String,
pub replica_identity: ReplicaIdentity,
pub columns: Vec<ColumnMetadata>,
pub revision: u64,
}
impl RelationMetadata {
#[must_use]
pub fn column_index(&self, name: &str) -> Option<usize> {
self.columns.iter().position(|column| column.name == name)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ColumnValue {
Null,
ToastUnchanged,
Text(String),
Binary(Vec<u8>),
}
impl ColumnValue {
#[must_use]
pub fn as_text(&self) -> Option<&str> {
match self {
Self::Text(value) => Some(value),
Self::Null | Self::ToastUnchanged | Self::Binary(_) => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RowData {
pub values: Vec<ColumnValue>,
}
impl RowData {
#[must_use]
pub fn get<'a>(
&'a self,
relation: &'a RelationMetadata,
column: &str,
) -> Option<&'a ColumnValue> {
relation
.column_index(column)
.and_then(|index| self.values.get(index))
}
#[must_use]
pub fn get_text<'a>(&'a self, relation: &'a RelationMetadata, column: &str) -> Option<&'a str> {
self.get(relation, column).and_then(ColumnValue::as_text)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ChangeOperation {
Insert,
Update,
Delete,
Truncate,
}
impl ChangeOperation {
#[must_use]
pub const fn debezium_letter(self) -> &'static str {
match self {
Self::Insert => "c",
Self::Update => "u",
Self::Delete => "d",
Self::Truncate => "t",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct TruncateOptions {
pub cascade: bool,
pub restart_identity: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct CdcOffset {
pub slot: String,
pub tx_end_lsn: PgLsn,
pub commit_lsn: PgLsn,
pub xid: u32,
pub event_index: u32,
pub event_count: u32,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TransactionMeta {
pub xid: u32,
pub commit_time_micros: i64,
pub event_index: u32,
pub event_count: u32,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ChangeEvent {
pub source: SourceMetadata,
pub schema: String,
pub table: String,
pub op: ChangeOperation,
pub before: Option<RowData>,
pub after: Option<RowData>,
pub truncate: Option<TruncateOptions>,
pub lsn: CdcOffset,
pub tx: TransactionMeta,
pub relation: RelationMetadata,
}