uqa_sql/plpgsql/
fragments.rs1use super::PLpgSQLCursorArgument;
10use crate::{
11 ast::{Expr, Statement},
12 SQLError,
13};
14use std::sync::Arc;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum PLpgSQLParseMode {
19 Statement,
20 Expression,
21 Assignment1,
22 Assignment2,
23 Assignment3,
24}
25impl TryFrom<i64> for PLpgSQLParseMode {
26 type Error = SQLError;
27 fn try_from(mode: i64) -> Result<Self, SQLError> {
28 match mode {
29 0 => Ok(Self::Statement),
30 2 => Ok(Self::Expression),
31 3 => Ok(Self::Assignment1),
32 4 => Ok(Self::Assignment2),
33 5 => Ok(Self::Assignment3),
34 _ => Err(SQLError::Internal(format!(
35 "invalid PL/pgSQL parse mode {mode}"
36 ))),
37 }
38 }
39}
40impl PLpgSQLParseMode {
41 pub(super) fn parser_mode(self) -> pg_query::ParseMode {
42 match self {
43 Self::Statement => pg_query::ParseMode::Default,
44 Self::Expression => pg_query::ParseMode::PlPgSqlExpr,
45 Self::Assignment1 => pg_query::ParseMode::PlPgSqlAssign1,
46 Self::Assignment2 => pg_query::ParseMode::PlPgSqlAssign2,
47 Self::Assignment3 => pg_query::ParseMode::PlPgSqlAssign3,
48 }
49 }
50}
51
52#[derive(Debug)]
55pub struct PLpgSQLSource {
56 pub query: Arc<str>,
57 pub mode: PLpgSQLParseMode,
58}
59
60#[derive(Debug, Clone)]
63pub struct PLpgSQLFragment<T> {
64 source: Arc<PLpgSQLSource>,
65 validation: Option<Arc<T>>,
66}
67impl<T> PLpgSQLFragment<T> {
68 pub(super) fn new(source: Arc<PLpgSQLSource>, validation: Option<T>) -> Self {
69 Self {
70 source,
71 validation: validation.map(Arc::new),
72 }
73 }
74 pub fn source(&self) -> &Arc<PLpgSQLSource> {
75 &self.source
76 }
77 pub fn validation(&self) -> Option<&T> {
78 self.validation.as_deref()
79 }
80 pub fn site(&self) -> usize {
82 Arc::as_ptr(&self.source) as usize
83 }
84}
85pub type PLpgSQLExpression = PLpgSQLFragment<Expr>;
86pub type PLpgSQLStatement = PLpgSQLFragment<Statement>;
87pub type PLpgSQLCursorArguments = PLpgSQLFragment<Vec<PLpgSQLCursorArgument>>;
88
89impl PLpgSQLExpression {
90 pub fn parse_statement(&self) -> Result<Statement, SQLError> {
91 self.parse()
92 .map(super::variable_conflicts::expression_query)
93 }
94 pub fn parse(&self) -> Result<Expr, SQLError> {
95 super::lowering_expression::compile_expression_source(&self.source)
96 }
97}
98impl PLpgSQLStatement {
99 pub fn parse(&self) -> Result<Statement, SQLError> {
100 super::lowering_expression::compile_statement_source(&self.source)
101 }
102}
103impl PLpgSQLCursorArguments {
104 pub fn parse_statement(&self) -> Result<Statement, SQLError> {
105 let arguments = self.parse()?;
106 let Statement::Select(mut query) =
107 super::variable_conflicts::expression_query(Expr::Literal(uqa_core::Value::Null))
108 else {
109 unreachable!()
110 };
111 query.projections = arguments
112 .into_iter()
113 .map(|argument| crate::ast::Projection {
114 expr: argument.expr,
115 alias: argument.name,
116 })
117 .collect();
118 Ok(Statement::Select(query))
119 }
120 pub fn parse(&self) -> Result<Vec<PLpgSQLCursorArgument>, SQLError> {
121 super::lowering_expression::compile_cursor_arguments_source(&self.source)
122 }
123 pub fn empty() -> Self {
124 Self::new(
125 Arc::new(PLpgSQLSource {
126 query: Arc::from(""),
127 mode: PLpgSQLParseMode::Expression,
128 }),
129 Some(Vec::new()),
130 )
131 }
132}
133
134#[derive(Debug, Clone, Default)]
137pub struct PLpgSQLCompilationIdentity(Arc<()>);
138impl PLpgSQLCompilationIdentity {
139 pub fn same(&self, other: &Self) -> bool {
140 Arc::ptr_eq(&self.0, &other.0)
141 }
142}
143
144#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
145pub enum PLpgSQLCompileMode {
146 #[default]
147 Validate,
148 Runtime,
149}
150impl PLpgSQLCompileMode {
151 pub(super) const fn validates(self) -> bool {
152 matches!(self, Self::Validate)
153 }
154}
155
156#[cfg(test)]
157mod tests;