1use std::any::Any;
16
17use api::v1::value::ValueData;
18use api::v1::{ColumnSchema, Row};
19use common_event_recorder::Event;
20use common_event_recorder::error::{Result, SerializeEventSnafu};
21use common_event_recorder::event_table::{
22 CATALOG_NAME_COLUMN, SCHEMA_NAME_COLUMN, VIEW_ID_COLUMN, VIEW_NAME_COLUMN, column_schemas,
23 nullable_string, nullable_value,
24};
25use serde::Serialize;
26use snafu::ResultExt;
27
28pub(crate) const CREATE_VIEW_EVENT_TYPE: &str = "create_view";
29pub(crate) const DROP_VIEW_EVENT_TYPE: &str = "drop_view";
30
31const PAYLOAD_VERSION: u8 = 1;
32
33#[derive(Debug)]
35pub(crate) struct CreateViewEventIntent {
36 pub(crate) or_replace: bool,
37 pub(crate) create_if_not_exists: bool,
38 pub(crate) referenced_table_count: usize,
39 pub(crate) column_count: usize,
40}
41
42#[derive(Debug, Serialize)]
43struct CreateViewPayload {
44 version: u8,
45 or_replace: bool,
46 create_if_not_exists: bool,
47 referenced_table_count: usize,
48 column_count: usize,
49}
50
51#[derive(Debug, Serialize)]
52struct DropViewPayload {
53 version: u8,
54 drop_if_exists: bool,
55}
56
57#[derive(Debug)]
58pub(crate) struct ViewDdlEvent {
59 event_type: &'static str,
60 catalog_name: Option<String>,
61 schema_name: Option<String>,
62 view_name: Option<String>,
63 view_id: Option<u32>,
64 payload: Option<ViewDdlPayload>,
65}
66
67#[derive(Debug, Serialize)]
68#[serde(untagged)]
69enum ViewDdlPayload {
70 Create(CreateViewPayload),
71 Drop(DropViewPayload),
72}
73
74impl ViewDdlEvent {
75 pub(crate) fn create_submitted(
77 catalog_name: &str,
78 schema_name: &str,
79 view_name: &str,
80 intent: CreateViewEventIntent,
81 ) -> Self {
82 Self::submitted(
83 CREATE_VIEW_EVENT_TYPE,
84 catalog_name,
85 schema_name,
86 view_name,
87 None,
88 ViewDdlPayload::Create(CreateViewPayload {
89 version: PAYLOAD_VERSION,
90 or_replace: intent.or_replace,
91 create_if_not_exists: intent.create_if_not_exists,
92 referenced_table_count: intent.referenced_table_count,
93 column_count: intent.column_count,
94 }),
95 )
96 }
97
98 pub(crate) fn drop_submitted(
100 catalog_name: &str,
101 schema_name: &str,
102 view_name: &str,
103 view_id: u32,
104 drop_if_exists: bool,
105 ) -> Self {
106 Self::submitted(
107 DROP_VIEW_EVENT_TYPE,
108 catalog_name,
109 schema_name,
110 view_name,
111 Some(view_id),
112 ViewDdlPayload::Drop(DropViewPayload {
113 version: PAYLOAD_VERSION,
114 drop_if_exists,
115 }),
116 )
117 }
118
119 pub(crate) fn create_lifecycle(catalog_name: &str, schema_name: &str, view_name: &str) -> Self {
121 Self::lifecycle(CREATE_VIEW_EVENT_TYPE, catalog_name, schema_name, view_name)
122 }
123
124 pub(crate) fn create_succeeded(
126 catalog_name: &str,
127 schema_name: &str,
128 view_name: &str,
129 view_id: u32,
130 ) -> Self {
131 Self::succeeded(
132 CREATE_VIEW_EVENT_TYPE,
133 catalog_name,
134 schema_name,
135 view_name,
136 view_id,
137 )
138 }
139
140 pub(crate) fn drop_lifecycle(
142 catalog_name: &str,
143 schema_name: &str,
144 view_name: &str,
145 view_id: u32,
146 ) -> Self {
147 Self {
148 view_id: Some(view_id),
149 ..Self::lifecycle(DROP_VIEW_EVENT_TYPE, catalog_name, schema_name, view_name)
150 }
151 }
152
153 fn submitted(
154 event_type: &'static str,
155 catalog_name: &str,
156 schema_name: &str,
157 view_name: &str,
158 view_id: Option<u32>,
159 payload: ViewDdlPayload,
160 ) -> Self {
161 Self {
162 event_type,
163 catalog_name: Some(catalog_name.to_string()),
164 schema_name: Some(schema_name.to_string()),
165 view_name: Some(view_name.to_string()),
166 view_id,
167 payload: Some(payload),
168 }
169 }
170
171 fn lifecycle(
172 event_type: &'static str,
173 catalog_name: &str,
174 schema_name: &str,
175 view_name: &str,
176 ) -> Self {
177 Self {
178 event_type,
179 catalog_name: Some(catalog_name.to_string()),
180 schema_name: Some(schema_name.to_string()),
181 view_name: Some(view_name.to_string()),
182 view_id: None,
183 payload: None,
184 }
185 }
186
187 fn succeeded(
188 event_type: &'static str,
189 catalog_name: &str,
190 schema_name: &str,
191 view_name: &str,
192 view_id: u32,
193 ) -> Self {
194 Self {
195 event_type,
196 catalog_name: Some(catalog_name.to_string()),
197 schema_name: Some(schema_name.to_string()),
198 view_name: Some(view_name.to_string()),
199 view_id: Some(view_id),
200 payload: None,
201 }
202 }
203}
204
205impl Event for ViewDdlEvent {
206 fn event_type(&self) -> &str {
207 self.event_type
208 }
209
210 fn json_payload(&self) -> Result<serde_json::Value> {
211 match &self.payload {
212 Some(payload) => serde_json::to_value(payload).context(SerializeEventSnafu),
213 None => Ok(serde_json::Value::Null),
214 }
215 }
216
217 fn extra_schema(&self) -> Vec<ColumnSchema> {
218 column_schemas([
219 &CATALOG_NAME_COLUMN,
220 &SCHEMA_NAME_COLUMN,
221 &VIEW_NAME_COLUMN,
222 &VIEW_ID_COLUMN,
223 ])
224 }
225
226 fn extra_rows(&self) -> Result<Vec<Row>> {
227 Ok(vec![Row {
228 values: vec![
229 nullable_string(self.catalog_name.as_deref()),
230 nullable_string(self.schema_name.as_deref()),
231 nullable_string(self.view_name.as_deref()),
232 nullable_value(self.view_id.map(ValueData::U32Value)),
233 ],
234 }])
235 }
236
237 fn as_any(&self) -> &dyn Any {
238 self
239 }
240}