1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//
// Unified Query Algebra
//
// Copyright (c) 2023-2026 Cognica, Inc.
//
//! The notices a session queues for its client.
use parking_lot::Mutex;
use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc;
use uqa_sql::semantics::parameters::catalog::message_levels;
use uqa_sql::SQLNotice;
/// The notices a session queues for its client, in the order they arrive. A notice below the session's `client_min_messages` is dropped as it arrives, as `PostgreSQL` decides whether a report reaches the client when it raises it (`errstart`), so a level that a function sets for its own body silences only the notices raised there.
pub struct NoticeQueue {
notices: Mutex<Vec<SQLNotice>>,
/// The session's `client_min_messages`, as a message level, which the session keeps current.
client_level: Arc<AtomicU8>,
}
impl Default for NoticeQueue {
fn default() -> Self {
Self::new(Arc::new(AtomicU8::new(message_levels::NOTICE)))
}
}
impl NoticeQueue {
/// A queue that reads the session's `client_min_messages` from `client_level`.
pub fn new(client_level: Arc<AtomicU8>) -> Self {
Self {
notices: Mutex::new(Vec::new()),
client_level,
}
}
/// Queue `notice` after the notices queued before it, unless its level does not reach the client.
pub fn push(&self, notice: SQLNotice) {
if notice
.level
.reaches_client(self.client_level.load(Ordering::Acquire))
{
self.notices.lock().push(notice);
}
}
/// Take every queued notice in the order they arrived.
pub fn take(&self) -> Vec<SQLNotice> {
std::mem::take(&mut *self.notices.lock())
}
/// The queued notices, left queued.
pub fn snapshot(&self) -> Vec<SQLNotice> {
self.notices.lock().clone()
}
pub fn len(&self) -> usize {
self.notices.lock().len()
}
pub fn is_empty(&self) -> bool {
self.notices.lock().is_empty()
}
}