vibesql_executor/
view_ddl.rs1use vibesql_ast::{CreateViewStmt, DropViewStmt};
4use vibesql_catalog::{ViewDefinition, ViewDropBehavior};
5use vibesql_storage::Database;
6
7use crate::errors::ExecutorError;
8
9pub struct ViewExecutor;
11
12impl ViewExecutor {
13 pub fn execute_create_view(
15 stmt: &CreateViewStmt,
16 database: &mut Database,
17 ) -> Result<String, ExecutorError> {
18 let view_exists = database.catalog.get_view(&stmt.view_name).is_some();
19
20 if stmt.if_not_exists && view_exists {
22 return Ok(format!("View '{}' already exists (skipped)", stmt.view_name));
23 }
24
25 if stmt.or_replace && view_exists {
27 database.catalog.drop_view(&stmt.view_name, false).map_err(|e| {
29 ExecutorError::StorageError(format!("Failed to drop existing view: {:?}", e))
30 })?;
31 }
32
33 let schema = if stmt.temporary { Some("temp".to_string()) } else { None };
37
38 let view_def = if let Some(ref sql) = stmt.sql_definition {
40 ViewDefinition::new_with_sql(
41 stmt.view_name.clone(),
42 stmt.columns.clone(),
43 *stmt.query.clone(),
44 stmt.with_check_option,
45 sql.clone(),
46 )
47 } else {
48 ViewDefinition::new(
49 stmt.view_name.clone(),
50 stmt.columns.clone(),
51 *stmt.query.clone(),
52 stmt.with_check_option,
53 )
54 }
55 .with_schema(schema);
56
57 database
59 .catalog
60 .create_view(view_def)
61 .map_err(|e| ExecutorError::StorageError(format!("Failed to create view: {:?}", e)))?;
62
63 if stmt.or_replace {
64 Ok(format!("View '{}' created or replaced", stmt.view_name))
65 } else {
66 Ok(format!("View '{}' created", stmt.view_name))
67 }
68 }
69
70 pub fn execute_drop_view(
72 stmt: &DropViewStmt,
73 database: &mut Database,
74 ) -> Result<String, ExecutorError> {
75 let drop_behavior = if stmt.cascade {
80 ViewDropBehavior::Cascade
81 } else if stmt.restrict {
82 ViewDropBehavior::Restrict
83 } else {
84 ViewDropBehavior::Silent };
86
87 let view_is_temp =
97 database.catalog.get_view(&stmt.view_name).is_some_and(|v| v.is_temp());
98
99 let result = database.catalog.drop_view_with_behavior(&stmt.view_name, drop_behavior);
101
102 match result {
103 Ok(()) => {
104 let dropped_triggers =
105 database.catalog.drop_view_triggers(&stmt.view_name, view_is_temp);
106 if dropped_triggers.is_empty() {
107 Ok(format!("View '{}' dropped", stmt.view_name))
108 } else {
109 Ok(format!(
110 "View '{}' and {} associated trigger(s) dropped",
111 stmt.view_name,
112 dropped_triggers.len()
113 ))
114 }
115 }
116 Err(e) => {
117 if stmt.if_exists
119 && matches!(e, vibesql_catalog::errors::CatalogError::ViewNotFound(_))
120 {
121 Ok(format!("View '{}' does not exist (skipped)", stmt.view_name))
122 } else {
123 Err(ExecutorError::StorageError(format!("Failed to drop view: {:?}", e)))
124 }
125 }
126 }
127 }
128}