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