1pub mod context;
16pub mod hints;
17pub mod protocol_ctx;
18pub mod query_id;
19pub mod query_options;
20pub mod session_config;
21pub mod table_name;
22
23use std::collections::{HashMap, VecDeque};
24use std::net::SocketAddr;
25use std::sync::{Arc, RwLock};
26use std::time::Duration;
27
28use auth::UserInfoRef;
29use common_catalog::build_db_string;
30use common_catalog::consts::{DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME};
31use common_recordbatch::cursor::RecordBatchStreamCursor;
32pub use common_session::ReadPreference;
33use common_time::Timezone;
34use common_time::timezone::get_timezone;
35use context::{ConfigurationVariables, QueryContextBuilder};
36use derive_more::Debug;
37
38use crate::context::{Channel, ConnInfo, QueryContextRef, dialect_for_channel};
39
40const MAX_WARNINGS: usize = 64;
42
43#[derive(Debug)]
45pub struct Session {
46 catalog: RwLock<String>,
47 mutable_inner: Arc<RwLock<MutableInner>>,
48 conn_info: ConnInfo,
49 configuration_variables: Arc<ConfigurationVariables>,
50 process_id: u32,
52}
53
54pub type SessionRef = Arc<Session>;
55
56#[derive(Debug, Clone)]
58pub(crate) struct MutableInner {
59 schema: String,
60 user_info: UserInfoRef,
61 timezone: Timezone,
62 query_timeout: Option<Duration>,
63 read_preference: ReadPreference,
64 last_procedure_id: Option<String>,
67 skip_wal: bool,
69 #[debug(skip)]
70 pub(crate) cursors: HashMap<String, Arc<RecordBatchStreamCursor>>,
71 warnings: VecDeque<String>,
73}
74
75impl Default for MutableInner {
76 fn default() -> Self {
77 Self {
78 schema: DEFAULT_SCHEMA_NAME.into(),
79 user_info: auth::userinfo_by_name(None),
80 timezone: get_timezone(None).clone(),
81 query_timeout: None,
82 read_preference: ReadPreference::Leader,
83 last_procedure_id: None,
84 skip_wal: false,
85 cursors: HashMap::with_capacity(0),
86 warnings: VecDeque::new(),
87 }
88 }
89}
90
91impl Session {
92 pub fn new(
93 addr: Option<SocketAddr>,
94 channel: Channel,
95 configuration_variables: ConfigurationVariables,
96 process_id: u32,
97 ) -> Self {
98 Session {
99 catalog: RwLock::new(DEFAULT_CATALOG_NAME.into()),
100 conn_info: ConnInfo::new(addr, channel),
101 configuration_variables: Arc::new(configuration_variables),
102 mutable_inner: Arc::new(RwLock::new(MutableInner::default())),
103 process_id,
104 }
105 }
106
107 pub fn new_query_context(&self) -> QueryContextRef {
108 QueryContextBuilder::default()
109 .current_catalog(self.catalog.read().unwrap().clone())
112 .mutable_session_data(self.mutable_inner.clone())
113 .sql_dialect(dialect_for_channel(self.conn_info.channel))
114 .configuration_parameter(self.configuration_variables.clone())
115 .channel(self.conn_info.channel)
116 .process_id(self.process_id)
117 .conn_info(self.conn_info.clone())
118 .build()
119 .into()
120 }
121
122 pub fn get_cursor(&self, name: &str) -> Option<Arc<RecordBatchStreamCursor>> {
124 let guard = self.mutable_inner.read().unwrap();
125 guard.cursors.get(name).cloned()
126 }
127
128 pub fn conn_info(&self) -> &ConnInfo {
129 &self.conn_info
130 }
131
132 pub fn timezone(&self) -> Timezone {
133 self.mutable_inner.read().unwrap().timezone.clone()
134 }
135
136 pub fn read_preference(&self) -> ReadPreference {
137 self.mutable_inner.read().unwrap().read_preference
138 }
139
140 pub fn set_timezone(&self, tz: Timezone) {
141 let mut inner = self.mutable_inner.write().unwrap();
142 inner.timezone = tz;
143 }
144
145 pub fn set_read_preference(&self, read_preference: ReadPreference) {
146 self.mutable_inner.write().unwrap().read_preference = read_preference;
147 }
148
149 pub fn user_info(&self) -> UserInfoRef {
150 self.mutable_inner.read().unwrap().user_info.clone()
151 }
152
153 pub fn set_user_info(&self, user_info: UserInfoRef) {
154 self.mutable_inner.write().unwrap().user_info = user_info;
155 }
156
157 pub fn set_catalog(&self, catalog: String) {
158 *self.catalog.write().unwrap() = catalog;
159 }
160
161 pub fn catalog(&self) -> String {
162 self.catalog.read().unwrap().clone()
163 }
164
165 pub fn schema(&self) -> String {
166 self.mutable_inner.read().unwrap().schema.clone()
167 }
168
169 pub fn set_schema(&self, schema: String) {
170 self.mutable_inner.write().unwrap().schema = schema;
171 }
172
173 pub fn get_db_string(&self) -> String {
174 build_db_string(&self.catalog(), &self.schema())
175 }
176
177 pub fn process_id(&self) -> u32 {
178 self.process_id
179 }
180
181 pub fn warnings_count(&self) -> usize {
182 self.mutable_inner.read().unwrap().warnings.len()
183 }
184
185 pub fn warnings(&self) -> Vec<String> {
186 self.mutable_inner
187 .read()
188 .unwrap()
189 .warnings
190 .iter()
191 .cloned()
192 .collect()
193 }
194
195 pub fn add_warning(&self, warning: String) {
197 let mut inner = self.mutable_inner.write().unwrap();
198 if inner.warnings.len() >= MAX_WARNINGS {
199 inner.warnings.pop_front();
200 }
201 inner.warnings.push_back(warning);
202 }
203
204 pub fn clear_warnings(&self) {
205 let mut inner = self.mutable_inner.write().unwrap();
206 if inner.warnings.is_empty() {
207 return;
208 }
209 inner.warnings.clear();
210 }
211}