Skip to main content

sentinel_driver/types/
ltree.rs

1use bytes::{BufMut, BytesMut};
2
3use crate::error::{Error, Result};
4use crate::types::{FromSql, Oid, ToSql};
5
6/// PostgreSQL LTREE type -- a dot-separated label path for hierarchical data.
7///
8/// LTREE is a PostgreSQL extension type used for representing labels of data
9/// stored in a hierarchical tree-like structure. Example: `"top.science.astronomy"`.
10///
11/// Wire format: UTF-8 text bytes (same as TEXT). Uses TEXT OID as carrier
12/// since LTREE is an extension type without a stable OID.
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct PgLTree(pub String);
15
16impl ToSql for PgLTree {
17    fn oid(&self) -> Oid {
18        Oid::TEXT
19    }
20
21    fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
22        buf.put_slice(self.0.as_bytes());
23        Ok(())
24    }
25}
26
27impl FromSql for PgLTree {
28    fn oid() -> Oid {
29        Oid::TEXT
30    }
31
32    fn from_sql(buf: &[u8]) -> Result<Self> {
33        let s = String::from_utf8(buf.to_vec())
34            .map_err(|e| Error::Decode(format!("ltree: invalid UTF-8: {e}")))?;
35        Ok(PgLTree(s))
36    }
37}
38
39impl std::fmt::Display for PgLTree {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        f.write_str(&self.0)
42    }
43}
44
45impl std::str::FromStr for PgLTree {
46    type Err = std::convert::Infallible;
47
48    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
49        Ok(PgLTree(s.to_owned()))
50    }
51}
52
53/// PostgreSQL LQUERY type -- a pattern for matching LTREE paths.
54///
55/// LQUERY extends LTREE with pattern-matching syntax including `*` (any label),
56/// `*{n}` (exactly n labels), and `*{n,m}` (between n and m labels).
57/// Example: `"*.science.*"` matches any path containing "science".
58///
59/// Wire format: UTF-8 text bytes (same as TEXT). Uses TEXT OID as carrier.
60#[derive(Debug, Clone, PartialEq, Eq, Hash)]
61pub struct PgLQuery(pub String);
62
63impl ToSql for PgLQuery {
64    fn oid(&self) -> Oid {
65        Oid::TEXT
66    }
67
68    fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
69        buf.put_slice(self.0.as_bytes());
70        Ok(())
71    }
72}
73
74impl FromSql for PgLQuery {
75    fn oid() -> Oid {
76        Oid::TEXT
77    }
78
79    fn from_sql(buf: &[u8]) -> Result<Self> {
80        let s = String::from_utf8(buf.to_vec())
81            .map_err(|e| Error::Decode(format!("lquery: invalid UTF-8: {e}")))?;
82        Ok(PgLQuery(s))
83    }
84}
85
86impl std::fmt::Display for PgLQuery {
87    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88        f.write_str(&self.0)
89    }
90}
91
92impl std::str::FromStr for PgLQuery {
93    type Err = std::convert::Infallible;
94
95    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
96        Ok(PgLQuery(s.to_owned()))
97    }
98}