Skip to main content

common_meta/ddl/event/
view.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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/// The bounded Create View intent allowed in a submitted event payload.
34#[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    /// Builds the bounded event emitted when creating a View is submitted.
76    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    /// Builds the bounded event emitted when dropping a View is submitted.
99    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    /// Builds a create-view lifecycle event with its submitted locator.
120    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    /// Builds the successful create-view row with its submitted locator and allocated ID.
125    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    /// Builds a drop-view lifecycle event with its submitted locator and ID.
141    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}