tests_fuzz/translator/postgres/
create_expr.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 datatypes::data_type::ConcreteDataType;
16use sql::statements::concrete_data_type_to_sql_data_type;
17
18use crate::error::{Error, Result};
19use crate::ir::create_expr::ColumnOption;
20use crate::ir::{Column, CreateTableExpr};
21use crate::translator::postgres::sql_data_type_to_postgres_data_type;
22use crate::translator::DslTranslator;
23
24pub struct CreateTableExprTranslator;
25
26impl DslTranslator<CreateTableExpr, String> for CreateTableExprTranslator {
27    type Error = Error;
28
29    fn translate(&self, input: &CreateTableExpr) -> Result<String> {
30        Ok(format!(
31            "CREATE TABLE{}{}(\n{}\n);",
32            Self::create_if_not_exists(input),
33            input.table_name,
34            Self::format_columns(input),
35        ))
36    }
37}
38
39impl CreateTableExprTranslator {
40    fn create_if_not_exists(input: &CreateTableExpr) -> &str {
41        if input.if_not_exists {
42            " IF NOT EXISTS "
43        } else {
44            " "
45        }
46    }
47
48    fn format_columns(input: &CreateTableExpr) -> String {
49        let mut output =
50            Vec::with_capacity(input.columns.len() + (!input.primary_keys.is_empty()) as usize);
51        for column in &input.columns {
52            output.push(Self::format_column(column));
53        }
54        output.join(",\n")
55    }
56
57    fn format_column(column: &Column) -> String {
58        vec![
59            column.name.to_string(),
60            Self::format_column_type(&column.column_type),
61            Self::format_column_options(&column.options),
62        ]
63        .into_iter()
64        .filter(|s| !s.is_empty())
65        .collect::<Vec<_>>()
66        .join(" ")
67    }
68
69    fn format_column_type(column_type: &ConcreteDataType) -> String {
70        sql_data_type_to_postgres_data_type(
71            // Safety: We don't use the `Dictionary` type
72            concrete_data_type_to_sql_data_type(column_type).unwrap(),
73        )
74    }
75
76    fn acceptable_column_option(option: &ColumnOption) -> bool {
77        matches!(
78            option,
79            ColumnOption::Null
80                | ColumnOption::NotNull
81                | ColumnOption::DefaultValue(_)
82                | ColumnOption::DefaultFn(_)
83        )
84    }
85
86    fn format_column_options(options: &[ColumnOption]) -> String {
87        let mut output = Vec::with_capacity(options.len());
88        for option in options {
89            if Self::acceptable_column_option(option) {
90                output.push(option.to_string());
91            }
92        }
93        output.join(" ")
94    }
95}