Skip to main content

pg2sqlite_core/ir/
model.rs

1/// Core IR model types for representing parsed DDL schemas.
2use super::expr::Expr;
3use super::ident::{Ident, QualifiedName};
4use super::types::{PgType, SqliteType};
5
6/// The top-level schema model containing all parsed DDL objects.
7#[derive(Debug, Clone, Default)]
8pub struct SchemaModel {
9    pub tables: Vec<Table>,
10    pub indexes: Vec<Index>,
11    pub sequences: Vec<Sequence>,
12    pub enums: Vec<EnumDef>,
13    pub domains: Vec<DomainDef>,
14    pub alter_constraints: Vec<AlterConstraint>,
15    pub identity_columns: Vec<AlterIdentity>,
16}
17
18/// A parsed CREATE TABLE statement.
19#[derive(Debug, Clone)]
20pub struct Table {
21    pub name: QualifiedName,
22    pub columns: Vec<Column>,
23    pub constraints: Vec<TableConstraint>,
24}
25
26/// A column definition within a table.
27#[derive(Debug, Clone)]
28pub struct Column {
29    pub name: Ident,
30    pub pg_type: PgType,
31    pub sqlite_type: Option<SqliteType>,
32    pub not_null: bool,
33    pub default: Option<Expr>,
34    pub is_primary_key: bool,
35    pub is_unique: bool,
36    pub autoincrement: bool,
37    pub references: Option<ForeignKeyRef>,
38    pub check: Option<Expr>,
39}
40
41/// Table-level constraint.
42#[derive(Debug, Clone)]
43pub enum TableConstraint {
44    PrimaryKey {
45        name: Option<Ident>,
46        columns: Vec<Ident>,
47    },
48    Unique {
49        name: Option<Ident>,
50        columns: Vec<Ident>,
51    },
52    ForeignKey {
53        name: Option<Ident>,
54        columns: Vec<Ident>,
55        ref_table: QualifiedName,
56        ref_columns: Vec<Ident>,
57        on_delete: Option<FkAction>,
58        on_update: Option<FkAction>,
59        deferrable: bool,
60    },
61    Check {
62        name: Option<Ident>,
63        expr: Expr,
64    },
65}
66
67/// An ALTER TABLE ... ADD CONSTRAINT that needs merging.
68#[derive(Debug, Clone)]
69pub struct AlterConstraint {
70    pub table: QualifiedName,
71    pub constraint: TableConstraint,
72}
73
74/// An ALTER TABLE ... ALTER COLUMN ... ADD GENERATED AS IDENTITY.
75#[derive(Debug, Clone)]
76pub struct AlterIdentity {
77    pub table: QualifiedName,
78    pub column: Ident,
79}
80
81/// Foreign key reference from a column-level constraint.
82#[derive(Debug, Clone)]
83pub struct ForeignKeyRef {
84    pub table: QualifiedName,
85    pub column: Option<Ident>,
86    pub on_delete: Option<FkAction>,
87    pub on_update: Option<FkAction>,
88}
89
90/// Foreign key referential action.
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92pub enum FkAction {
93    Cascade,
94    SetNull,
95    SetDefault,
96    Restrict,
97    NoAction,
98}
99
100impl std::fmt::Display for FkAction {
101    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102        match self {
103            FkAction::Cascade => write!(f, "CASCADE"),
104            FkAction::SetNull => write!(f, "SET NULL"),
105            FkAction::SetDefault => write!(f, "SET DEFAULT"),
106            FkAction::Restrict => write!(f, "RESTRICT"),
107            FkAction::NoAction => write!(f, "NO ACTION"),
108        }
109    }
110}
111
112/// A CREATE INDEX statement.
113#[derive(Debug, Clone)]
114pub struct Index {
115    pub name: Ident,
116    pub table: QualifiedName,
117    pub columns: Vec<IndexColumn>,
118    pub unique: bool,
119    pub method: Option<IndexMethod>,
120    pub where_clause: Option<Expr>,
121}
122
123/// A column or expression in an index.
124#[derive(Debug, Clone)]
125pub enum IndexColumn {
126    Column(Ident),
127    Expression(Expr),
128}
129
130/// Index access method.
131#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132pub enum IndexMethod {
133    Btree,
134    Hash,
135    Gin,
136    Gist,
137    SpGist,
138    Brin,
139}
140
141impl std::fmt::Display for IndexMethod {
142    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143        match self {
144            IndexMethod::Btree => write!(f, "btree"),
145            IndexMethod::Hash => write!(f, "hash"),
146            IndexMethod::Gin => write!(f, "gin"),
147            IndexMethod::Gist => write!(f, "gist"),
148            IndexMethod::SpGist => write!(f, "spgist"),
149            IndexMethod::Brin => write!(f, "brin"),
150        }
151    }
152}
153
154/// A CREATE SEQUENCE statement.
155#[derive(Debug, Clone)]
156pub struct Sequence {
157    pub name: QualifiedName,
158    pub owned_by: Option<(QualifiedName, Ident)>,
159}
160
161/// A CREATE TYPE ... AS ENUM statement.
162#[derive(Debug, Clone)]
163pub struct EnumDef {
164    pub name: QualifiedName,
165    pub values: Vec<String>,
166}
167
168/// A CREATE DOMAIN statement.
169#[derive(Debug, Clone)]
170pub struct DomainDef {
171    pub name: QualifiedName,
172    pub base_type: PgType,
173    pub not_null: bool,
174    pub default: Option<Expr>,
175    pub check: Option<Expr>,
176}