Skip to main content

safe_migrate/ast/
identifiers.rs

1// FILE: ./src/ast/identifiers.rs
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
6pub struct Ident {
7    pub text: String,
8    pub quoted: bool,
9}
10
11impl Ident {
12    pub fn new(text: impl Into<String>, quoted: bool) -> Self {
13        Self {
14            text: text.into(),
15            quoted,
16        }
17    }
18
19    /// Resolves the identifier exactly as PostgreSQL would:
20    /// Quoted identifiers preserve exact casing; unquoted identifiers are case-folded to lowercase.
21    pub fn resolve(&self) -> String {
22        if self.quoted {
23            self.text.clone()
24        } else {
25            self.text.to_lowercase()
26        }
27    }
28}
29
30#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
31pub struct QualifiedName {
32    pub schema: Option<Ident>,
33    pub name: Ident,
34}
35
36impl QualifiedName {
37    pub fn new(schema: Option<Ident>, name: Ident) -> Self {
38        Self { schema, name }
39    }
40}
41
42/// ObjectId represents a fully resolved, state-machine tracked database object.
43/// By the time an ObjectId is constructed, its schema and name must already be properly case-folded.
44#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
45pub struct ObjectId {
46    pub schema: String,
47    pub name: String,
48}
49
50impl ObjectId {
51    pub fn new(schema: impl Into<String>, name: impl Into<String>) -> Self {
52        Self {
53            schema: schema.into(),
54            name: name.into(),
55        }
56    }
57}
58
59impl std::fmt::Display for ObjectId {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        write!(f, "{}.{}", self.schema, self.name)
62    }
63}