Skip to main content

sql_fun_sqlast/sem/
create_table_as.rs

1use sql_fun_core::IVec;
2
3use crate::{
4    sem::{AstAndContextPair, alter_table::AlterObjSubCommand, create_table::ColumnDefinition},
5    syn::{ObjectType, Opt, ScanToken},
6};
7
8use super::{AlterView, AnalysisError, CreateTable, FullName, ParseContext, SemAst, TableName};
9
10/// analyzed [`crate::syn::CreateTableAsStmt`]
11#[derive(Debug, Clone)]
12pub struct CreateTableAs {
13    name: FullName,
14    #[expect(dead_code)]
15    query: Box<SemAst>,
16    obj_type: ObjectType,
17    owner: Option<String>,
18    alter_statements: Vec<AlterView>,
19}
20
21impl CreateTableAs {
22    /// object name
23    #[must_use]
24    pub fn name(&self) -> &FullName {
25        &self.name
26    }
27
28    /// object type
29    #[must_use]
30    pub fn obj_type(&self) -> ObjectType {
31        self.obj_type
32    }
33
34    pub(crate) fn apply_alter(&mut self, alter_view: &AlterView) -> Result<(), AnalysisError> {
35        self.alter_statements.push(alter_view.clone());
36
37        for cmd in alter_view.commands() {
38            match cmd {
39                AlterObjSubCommand::ChangeOwner(new_owner) => self.owner = Some(new_owner.clone()),
40                _ => todo!(),
41            }
42        }
43
44        Ok(())
45    }
46
47    pub(crate) fn get_column_def(
48        &self,
49        _column_name: &super::ColumnName,
50    ) -> Option<ColumnDefinition> {
51        todo!()
52    }
53
54    pub(crate) fn has_column(&self, _column_name: &super::ColumnName) -> bool {
55        todo!()
56    }
57}
58
59/// analyze [`crate::syn::CreateTableAsStmt`]
60#[tracing::instrument(skip_all)]
61pub fn analyze_create_table_as<TParseContext>(
62    context: TParseContext,
63    parent_schema: &Option<String>,
64    syn: crate::syn::CreateTableAsStmt,
65    tokens: &IVec<ScanToken>,
66) -> Result<AstAndContextPair<TParseContext>, AnalysisError>
67where
68    TParseContext: ParseContext,
69{
70    let Some(obj_type) = syn.get_objtype().as_inner() else {
71        AnalysisError::raise_unexpected_none("create_table_as.obj_type")?
72    };
73
74    let Some(into) = syn.get_into().as_inner() else {
75        AnalysisError::raise_unexpected_none("create_table_as.into")?
76    };
77    let Some(into_rel) = into.get_rel().as_inner() else {
78        AnalysisError::raise_unexpected_none("into_clause.rel")?
79    };
80    let name = FullName::try_from(into_rel.clone())?;
81    let Some(q) = syn.get_query().as_inner() else {
82        AnalysisError::raise_unexpected_none("create_table_as.query")?
83    };
84    let AstAndContextPair(sem, context) = super::analyze_node(context, parent_schema, q, tokens)?;
85    let context = match &sem {
86        SemAst::SelectStatement(s) => {
87            let columns = s.result_columns().column_definitions()?;
88            let create_table = CreateTable::new(TableName::try_from(into_rel)?, columns);
89            context.apply_create_table(&create_table)?
90        }
91        _ => AnalysisError::raise_unexpected_none("SemAst As Select statement")?,
92    };
93    let create_table_as = CreateTableAs {
94        name,
95        query: Box::new(sem),
96        obj_type,
97        owner: None,
98        alter_statements: Vec::new(),
99    };
100    let result_context = context.apply_create_table_as(&create_table_as)?;
101    Ok(AstAndContextPair::new(
102        SemAst::CreateTableAs(create_table_as),
103        result_context,
104    ))
105}