halo/
create_table.rs

1//! CreateTableBuilder:构建 CREATE TABLE(对齐 go-sqlbuilder `createtable.go`)。
2
3use crate::args::Args;
4use crate::flavor::Flavor;
5use crate::injection::{Injection, InjectionMarker};
6use crate::modifiers::{Arg, Builder, escape};
7use crate::string_builder::StringBuilder;
8use std::cell::RefCell;
9use std::rc::Rc;
10
11const CT_MARKER_INIT: InjectionMarker = 0;
12const CT_MARKER_AFTER_CREATE: InjectionMarker = 1;
13const CT_MARKER_AFTER_DEFINE: InjectionMarker = 2;
14const CT_MARKER_AFTER_OPTION: InjectionMarker = 3;
15
16#[derive(Debug, Clone)]
17pub struct CreateTableBuilder {
18    verb: &'static str,
19    if_not_exists: bool,
20    table: Option<String>,
21    defs: Vec<Vec<String>>,
22    options: Vec<Vec<String>>,
23
24    args: Rc<RefCell<Args>>,
25    injection: Injection,
26    marker: InjectionMarker,
27}
28
29impl Default for CreateTableBuilder {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34
35impl CreateTableBuilder {
36    pub fn new() -> Self {
37        Self {
38            verb: "CREATE TABLE",
39            if_not_exists: false,
40            table: None,
41            defs: Vec::new(),
42            options: Vec::new(),
43            args: Rc::new(RefCell::new(Args::default())),
44            injection: Injection::new(),
45            marker: CT_MARKER_INIT,
46        }
47    }
48
49    pub fn set_flavor(&mut self, flavor: Flavor) -> Flavor {
50        let mut a = self.args.borrow_mut();
51        let old = a.flavor;
52        a.flavor = flavor;
53        old
54    }
55
56    pub fn flavor(&self) -> Flavor {
57        self.args.borrow().flavor
58    }
59
60    pub fn create_table(&mut self, table: &str) -> &mut Self {
61        self.table = Some(escape(table));
62        self.marker = CT_MARKER_AFTER_CREATE;
63        self
64    }
65
66    pub fn create_temp_table(&mut self, table: &str) -> &mut Self {
67        self.verb = "CREATE TEMPORARY TABLE";
68        self.table = Some(escape(table));
69        self.marker = CT_MARKER_AFTER_CREATE;
70        self
71    }
72
73    pub fn if_not_exists(&mut self) -> &mut Self {
74        self.if_not_exists = true;
75        self
76    }
77
78    pub fn define(&mut self, def: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
79        self.defs.push(def.into_iter().map(Into::into).collect());
80        self.marker = CT_MARKER_AFTER_DEFINE;
81        self
82    }
83
84    pub fn option(&mut self, opt: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
85        self.options.push(opt.into_iter().map(Into::into).collect());
86        self.marker = CT_MARKER_AFTER_OPTION;
87        self
88    }
89
90    pub fn sql(&mut self, sql: impl Into<String>) -> &mut Self {
91        self.injection.sql(self.marker, sql);
92        self
93    }
94
95    pub fn num_define(&self) -> usize {
96        self.defs.len()
97    }
98
99    // CreateTableBuilder 当前不需要参数占位符;后续如需要可再引入。
100}
101
102impl Builder for CreateTableBuilder {
103    fn build_with_flavor(&self, flavor: Flavor, initial_arg: &[Arg]) -> (String, Vec<Arg>) {
104        let mut buf = StringBuilder::new();
105        write_injection(&mut buf, &self.injection, CT_MARKER_INIT);
106
107        buf.write_leading(self.verb);
108        if self.if_not_exists {
109            buf.write_leading("IF NOT EXISTS");
110        }
111        if let Some(t) = &self.table {
112            buf.write_leading(t);
113        }
114        write_injection(&mut buf, &self.injection, CT_MARKER_AFTER_CREATE);
115
116        if !self.defs.is_empty() {
117            let defs: Vec<String> = self.defs.iter().map(|d| d.join(" ")).collect();
118            buf.write_leading("(");
119            buf.write_str(&defs.join(", "));
120            buf.write_str(")");
121            write_injection(&mut buf, &self.injection, CT_MARKER_AFTER_DEFINE);
122        }
123
124        if !self.options.is_empty() {
125            let opts: Vec<String> = self.options.iter().map(|o| o.join(" ")).collect();
126            buf.write_leading(&opts.join(", "));
127            write_injection(&mut buf, &self.injection, CT_MARKER_AFTER_OPTION);
128        }
129
130        // flavor 参数目前仅影响占位符;CreateTable 本身一般不产生占位符
131        let _ = flavor;
132        self.args
133            .borrow()
134            .compile_with_flavor(&buf.into_string(), self.flavor(), initial_arg)
135    }
136
137    fn flavor(&self) -> Flavor {
138        self.flavor()
139    }
140}
141
142pub fn create_table(table: impl Into<String>) -> CreateTableBuilder {
143    let mut builder = CreateTableBuilder::new();
144    builder.create_table(&table.into());
145    builder
146}
147
148pub fn create_temp_table(table: impl Into<String>) -> CreateTableBuilder {
149    let mut builder = CreateTableBuilder::new();
150    builder.create_temp_table(&table.into());
151    builder
152}
153
154fn write_injection(buf: &mut StringBuilder, inj: &Injection, marker: InjectionMarker) {
155    let sqls = inj.at(marker);
156    if sqls.is_empty() {
157        return;
158    }
159    buf.write_leading("");
160    buf.write_str(&sqls.join(" "));
161}