1use crate::ParamValue;
2use serde::{Deserialize, Serialize};
3use std::time::{Duration, SystemTime};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct QueryEvent {
8 pub event_id: String,
10
11 pub timestamp: SystemTime,
13
14 pub query: String,
16
17 #[serde(default, skip_serializing_if = "Vec::is_empty")]
19 pub params: Vec<ParamValue>,
20
21 #[serde(default)]
23 pub params_incomplete: bool,
24
25 #[serde(skip_serializing_if = "Option::is_none")]
27 pub normalized_query: Option<String>,
28
29 #[serde(skip_serializing_if = "Option::is_none")]
32 pub value_fingerprints: Option<Vec<String>>,
33
34 pub duration: Duration,
36
37 pub rows: Option<u64>,
39
40 pub success: bool,
42
43 pub error: Option<String>,
45
46 pub database: String,
48
49 pub connection_id: String,
51}
52
53pub struct QueryEventBuilder {
55 event_id: String,
56 timestamp: SystemTime,
57 query: String,
58 params: Vec<ParamValue>,
59 params_incomplete: bool,
60 normalized_query: Option<String>,
61 value_fingerprints: Option<Vec<String>>,
62 duration: Option<Duration>,
63 rows: Option<u64>,
64 success: bool,
65 error: Option<String>,
66 database: String,
67 connection_id: String,
68}
69
70impl QueryEventBuilder {
71 pub fn new(query: impl Into<String>) -> Self {
72 Self {
73 event_id: uuid::Uuid::new_v4().to_string(),
74 timestamp: SystemTime::now(),
75 query: query.into(),
76 params: Vec::new(),
77 params_incomplete: false,
78 normalized_query: None,
79 value_fingerprints: None,
80 duration: None,
81 rows: None,
82 success: true,
83 error: None,
84 database: String::from("unknown"),
85 connection_id: String::from("unknown"),
86 }
87 }
88
89 pub fn params(mut self, params: Vec<ParamValue>) -> Self {
90 self.params = params;
91 self
92 }
93
94 pub fn params_incomplete(mut self, incomplete: bool) -> Self {
95 self.params_incomplete = incomplete;
96 self
97 }
98
99 pub fn normalized_query(mut self, normalized_query: impl Into<String>) -> Self {
100 self.normalized_query = Some(normalized_query.into());
101 self
102 }
103
104 pub fn value_fingerprints(mut self, fingerprints: Vec<String>) -> Self {
105 self.value_fingerprints = Some(fingerprints);
106 self
107 }
108
109 pub fn duration(mut self, duration: Duration) -> Self {
110 self.duration = Some(duration);
111 self
112 }
113
114 pub fn rows(mut self, rows: u64) -> Self {
115 self.rows = Some(rows);
116 self
117 }
118
119 pub fn success(mut self, success: bool) -> Self {
120 self.success = success;
121 self
122 }
123
124 pub fn error(mut self, error: impl Into<String>) -> Self {
125 self.error = Some(error.into());
126 self
127 }
128
129 pub fn database(mut self, database: impl Into<String>) -> Self {
130 self.database = database.into();
131 self
132 }
133
134 pub fn connection_id(mut self, connection_id: impl Into<String>) -> Self {
135 self.connection_id = connection_id.into();
136 self
137 }
138
139 pub fn build(self) -> QueryEvent {
140 QueryEvent {
141 event_id: self.event_id,
142 timestamp: self.timestamp,
143 query: self.query,
144 params: self.params,
145 params_incomplete: self.params_incomplete,
146 normalized_query: self.normalized_query,
147 value_fingerprints: self.value_fingerprints,
148 duration: self.duration.unwrap_or(Duration::from_millis(0)),
149 rows: self.rows,
150 success: self.success,
151 error: self.error,
152 database: self.database,
153 connection_id: self.connection_id,
154 }
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use crate::ParamValue;
162
163 #[test]
164 fn test_query_event_with_params() {
165 let event = QueryEventBuilder::new("SELECT * FROM users WHERE id = $1")
166 .params(vec![ParamValue::Int32(42)])
167 .build();
168
169 assert_eq!(event.params.len(), 1);
170 assert!(!event.params_incomplete);
171 }
172
173 #[test]
174 fn test_query_event_params_incomplete() {
175 let event = QueryEventBuilder::new("SELECT * FROM users WHERE id = $1")
176 .params(vec![ParamValue::Unknown { oid: 0, data: vec![0x01] }])
177 .params_incomplete(true)
178 .build();
179
180 assert!(event.params_incomplete);
181 }
182}