1use crate::error::{QuillSQLError, QuillSQLResult};
2use crate::transaction::{IsolationLevel, Transaction};
3use sqlparser::ast::TransactionAccessMode;
4use std::sync::Arc;
5pub struct SessionContext {
7 default_isolation: IsolationLevel,
8 default_access_mode: TransactionAccessMode,
9 autocommit: bool,
10 active_txn: Option<Transaction>,
11 pending_session_isolation: Option<IsolationLevel>,
12 pending_session_access: Option<TransactionAccessMode>,
13}
14
15impl SessionContext {
16 pub fn new(default_isolation: IsolationLevel) -> Self {
17 Self {
18 default_isolation,
19 default_access_mode: TransactionAccessMode::ReadWrite,
20 autocommit: true,
21 active_txn: None,
22 pending_session_isolation: None,
23 pending_session_access: None,
24 }
25 }
26
27 pub fn default_isolation(&self) -> IsolationLevel {
28 self.default_isolation
29 }
30
31 pub fn set_default_isolation(&mut self, isolation: IsolationLevel) {
32 self.default_isolation = isolation;
33 }
34
35 pub fn default_access_mode(&self) -> TransactionAccessMode {
36 self.default_access_mode
37 }
38
39 pub fn set_default_access_mode(&mut self, mode: TransactionAccessMode) {
40 self.default_access_mode = mode;
41 }
42
43 pub fn set_active_isolation(&mut self, isolation: IsolationLevel) {
45 if let Some(txn) = self.active_txn.as_mut() {
46 txn.set_isolation_level(isolation);
47 }
48 }
49
50 pub fn autocommit(&self) -> bool {
51 self.autocommit
52 }
53
54 pub fn set_autocommit(&mut self, enabled: bool) {
55 self.autocommit = enabled;
56 }
57
58 pub fn pending_session_isolation(&self) -> Option<IsolationLevel> {
60 self.pending_session_isolation
61 }
62
63 pub fn set_pending_session_isolation(&mut self, isolation: Option<IsolationLevel>) {
65 self.pending_session_isolation = isolation;
66 }
67
68 pub fn pending_session_access(&self) -> Option<TransactionAccessMode> {
69 self.pending_session_access
70 }
71
72 pub fn set_pending_session_access(&mut self, mode: Option<TransactionAccessMode>) {
73 self.pending_session_access = mode;
74 }
75
76 pub fn has_active_transaction(&self) -> bool {
77 self.active_txn.is_some()
78 }
79
80 pub fn active_txn(&self) -> Option<&Transaction> {
81 self.active_txn.as_ref()
82 }
83
84 pub fn active_txn_mut(&mut self) -> Option<&mut Transaction> {
85 self.active_txn.as_mut()
86 }
87
88 pub fn ensure_active_transaction(
89 &mut self,
90 txn_mgr: &Arc<crate::transaction::TransactionManager>,
91 ) -> QuillSQLResult<&mut Transaction> {
92 if self.active_txn.is_none() {
93 let isolation = self
94 .pending_session_isolation
95 .unwrap_or(self.default_isolation);
96 let access_mode = self
97 .pending_session_access
98 .unwrap_or(self.default_access_mode);
99 let mut txn = txn_mgr.begin(isolation, access_mode)?;
100 if let Some(isolation) = self.pending_session_isolation.take() {
101 self.default_isolation = isolation;
102 txn.set_isolation_level(isolation);
103 }
104 if let Some(mode) = self.pending_session_access.take() {
105 self.default_access_mode = mode;
106 txn.update_access_mode(mode);
107 }
108 self.active_txn = Some(txn);
109 }
110 self.active_txn
111 .as_mut()
112 .ok_or_else(|| QuillSQLError::Execution("failed to start transaction".to_string()))
113 }
114
115 pub fn set_active_transaction(&mut self, mut txn: Transaction) -> QuillSQLResult<()> {
116 if self.active_txn.is_some() {
117 return Err(QuillSQLError::Execution(
118 "transaction already active in session".to_string(),
119 ));
120 }
121 if let Some(isolation) = self.pending_session_isolation.take() {
122 self.default_isolation = isolation;
123 txn.set_isolation_level(isolation);
124 } else {
125 self.default_isolation = txn.isolation_level();
126 }
127
128 if let Some(mode) = self.pending_session_access.take() {
129 self.default_access_mode = mode;
130 txn.update_access_mode(mode);
131 } else {
132 self.default_access_mode = txn.access_mode();
133 }
134
135 self.active_txn = Some(txn);
136 Ok(())
137 }
138
139 pub fn take_active_transaction(&mut self) -> Option<Transaction> {
140 self.active_txn.take()
141 }
142
143 pub fn clear_active_transaction(&mut self) {
144 self.active_txn = None;
145 }
146
147 pub fn apply_transaction_modes(&mut self, modes: &crate::plan::logical_plan::TransactionModes) {
149 if let Some(level) = modes.isolation_level {
150 if let Some(txn) = self.active_txn.as_mut() {
151 txn.set_isolation_level(level);
152 }
153 }
154 if let Some(mode) = modes.access_mode {
155 if let Some(txn) = self.active_txn.as_mut() {
156 txn.update_access_mode(mode);
157 }
158 }
159 }
160
161 pub fn apply_session_modes(&mut self, modes: &crate::plan::logical_plan::TransactionModes) {
163 if let Some(level) = modes.isolation_level {
164 self.default_isolation = level;
165 self.pending_session_isolation = Some(level);
166 }
167 if let Some(mode) = modes.access_mode {
168 self.default_access_mode = mode;
169 self.pending_session_access = Some(mode);
170 }
171 }
172}