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