1use std::collections::HashMap;
38use std::sync::{Arc, RwLock};
39
40use pylon_core::ir::SessionConfig;
41use pylon_core::schema::SchemaDescriptor;
42use pylon_value::DecodedValue;
43
44use crate::error::Result;
45use crate::exec;
46use crate::query_arg::QueryArgs;
47use crate::queryable::{Queryable, decode_optional_row, decode_row, decode_rows};
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
52pub enum Isolation {
53 ReadUncommitted,
54 ReadCommitted,
55 RepeatableRead,
56 #[default]
57 Serializable,
58}
59
60impl Isolation {
61 pub(crate) fn as_str(self) -> &'static str {
62 match self {
63 Isolation::ReadUncommitted => "read_uncommitted",
64 Isolation::ReadCommitted => "read_committed",
65 Isolation::RepeatableRead => "repeatable_read",
66 Isolation::Serializable => "serializable",
67 }
68 }
69}
70
71pub struct Transaction {
76 pub(crate) inner: pylon_pgcon::PgTransaction,
77 pub(crate) schema: Arc<RwLock<SchemaDescriptor>>,
78 pub(crate) config: SessionConfig,
79 pub(crate) globals: Arc<HashMap<String, DecodedValue>>,
80 pub(crate) cache: Option<Arc<pylon_cache::Cache>>,
83}
84
85impl Transaction {
86 pub async fn query<R: Queryable, A: QueryArgs + ?Sized>(&self, pyql: &str, args: &A) -> Result<Vec<R>> {
94 let params = args.to_params();
95 let schema = self.schema.read().unwrap().clone();
96 let values = exec::query(
97 &self.inner,
98 pyql,
99 ¶ms,
100 &schema,
101 &self.config,
102 &self.globals,
103 crate::cache::CacheAccess::evict_only(self.cache.as_deref()),
104 )
105 .await?;
106 decode_rows(values)
107 }
108
109 pub async fn query_single<R: Queryable, A: QueryArgs + ?Sized>(&self, pyql: &str, args: &A) -> Result<Option<R>> {
110 let params = args.to_params();
111 let schema = self.schema.read().unwrap().clone();
112 let values = exec::query_single(
113 &self.inner,
114 pyql,
115 ¶ms,
116 &schema,
117 &self.config,
118 &self.globals,
119 crate::cache::CacheAccess::evict_only(self.cache.as_deref()),
120 )
121 .await?;
122 decode_optional_row(values)
123 }
124
125 pub async fn query_required_single<R: Queryable, A: QueryArgs + ?Sized>(&self, pyql: &str, args: &A) -> Result<R> {
126 let params = args.to_params();
127 let schema = self.schema.read().unwrap().clone();
128 let values = exec::query_required_single(
129 &self.inner,
130 pyql,
131 ¶ms,
132 &schema,
133 &self.config,
134 &self.globals,
135 crate::cache::CacheAccess::evict_only(self.cache.as_deref()),
136 )
137 .await?;
138 decode_row(values)
139 }
140
141 pub async fn execute<A: QueryArgs + ?Sized>(&self, pyql: &str, args: &A) -> Result<()> {
145 let params = args.to_params();
146 let schema = self.schema.read().unwrap().clone();
147 exec::execute(
148 &self.inner,
149 pyql,
150 ¶ms,
151 &schema,
152 &self.config,
153 &self.globals,
154 crate::cache::CacheAccess::evict_only(self.cache.as_deref()),
155 )
156 .await
157 }
158
159 pub async fn query_json<A: QueryArgs + ?Sized>(&self, pyql: &str, args: &A) -> Result<String> {
160 let params = args.to_params();
161 let schema = self.schema.read().unwrap().clone();
162 exec::query_json(
163 &self.inner,
164 pyql,
165 ¶ms,
166 &schema,
167 &self.config,
168 &self.globals,
169 crate::cache::CacheAccess::evict_only(self.cache.as_deref()),
170 )
171 .await
172 }
173
174 pub async fn query_single_json<A: QueryArgs + ?Sized>(&self, pyql: &str, args: &A) -> Result<Option<String>> {
175 let params = args.to_params();
176 let schema = self.schema.read().unwrap().clone();
177 exec::query_single_json(
178 &self.inner,
179 pyql,
180 ¶ms,
181 &schema,
182 &self.config,
183 &self.globals,
184 crate::cache::CacheAccess::evict_only(self.cache.as_deref()),
185 )
186 .await
187 }
188
189 pub async fn query_required_single_json<A: QueryArgs + ?Sized>(&self, pyql: &str, args: &A) -> Result<String> {
190 let params = args.to_params();
191 let schema = self.schema.read().unwrap().clone();
192 exec::query_required_single_json(
193 &self.inner,
194 pyql,
195 ¶ms,
196 &schema,
197 &self.config,
198 &self.globals,
199 crate::cache::CacheAccess::evict_only(self.cache.as_deref()),
200 )
201 .await
202 }
203}