1use super::*;
16
17#[derive(Debug, Clone, PartialEq)]
19pub struct CreateExtensionStatement {
20 pub token: Token,
21 pub name: Identifier,
22 pub version: SmartString,
23 pub if_not_exists: bool,
24}
25
26impl fmt::Display for CreateExtensionStatement {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 write!(f, "CREATE EXTENSION ")?;
29 if self.if_not_exists {
30 write!(f, "IF NOT EXISTS ")?;
31 }
32 write!(
33 f,
34 "{} VERSION '{}'",
35 self.name,
36 escape_sql_string(&self.version)
37 )
38 }
39}
40
41#[derive(Debug, Clone, PartialEq)]
43pub struct DropExtensionStatement {
44 pub token: Token,
45 pub name: Identifier,
46 pub if_exists: bool,
47}
48
49impl fmt::Display for DropExtensionStatement {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 write!(f, "DROP EXTENSION ")?;
52 if self.if_exists {
53 write!(f, "IF EXISTS ")?;
54 }
55 write!(f, "{} RESTRICT", self.name)
56 }
57}
58
59#[derive(Debug, Clone, PartialEq)]
61pub struct CreateExternalTypeStatement {
62 pub token: Token,
63 pub name: ObjectName,
64 pub extension_name: Identifier,
65 pub local_id: SmartString,
66}
67
68impl fmt::Display for CreateExternalTypeStatement {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(
71 f,
72 "CREATE TYPE {} FROM EXTENSION {} AS '{}'",
73 self.name,
74 self.extension_name,
75 escape_sql_string(&self.local_id)
76 )
77 }
78}
79
80#[derive(Debug, Clone, PartialEq)]
82pub struct DropExternalTypeStatement {
83 pub token: Token,
84 pub name: ObjectName,
85 pub if_exists: bool,
86}
87
88#[derive(Debug, Clone, PartialEq)]
89pub struct QualifiedOperator {
90 pub schema: Identifier,
91 pub symbol: SmartString,
92}
93
94impl fmt::Display for QualifiedOperator {
95 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
96 write!(formatter, "{}.{}", self.schema, self.symbol)
97 }
98}
99
100#[derive(Debug, Clone, PartialEq)]
101pub struct CreateOperatorStatement {
102 pub token: Token,
103 pub name: QualifiedOperator,
104 pub left_argument: Option<ProceduralType>,
105 pub right_argument: ProceduralType,
106 pub function: RoutineSignatureSyntax,
107 pub extension_name: Identifier,
108 pub local_id: SmartString,
109}
110
111impl fmt::Display for CreateOperatorStatement {
112 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
113 write!(formatter, "CREATE OPERATOR {} (", self.name)?;
114 if let Some(left) = &self.left_argument {
115 write!(formatter, "LEFTARG = {left}, ")?;
116 }
117 write!(
118 formatter,
119 "RIGHTARG = {}, FUNCTION = {}) FROM EXTENSION {} AS '{}'",
120 self.right_argument,
121 self.function,
122 self.extension_name,
123 escape_sql_string(&self.local_id)
124 )
125 }
126}
127
128#[derive(Debug, Clone, PartialEq)]
129pub struct DropOperatorStatement {
130 pub token: Token,
131 pub name: QualifiedOperator,
132 pub left_argument: Option<ProceduralType>,
133 pub right_argument: Option<ProceduralType>,
134 pub if_exists: bool,
135}
136
137impl fmt::Display for DropOperatorStatement {
138 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
139 formatter.write_str("DROP OPERATOR ")?;
140 if self.if_exists {
141 formatter.write_str("IF EXISTS ")?;
142 }
143 write!(formatter, "{} (", self.name)?;
144 if let Some(left) = &self.left_argument {
145 write!(formatter, "{left}")?;
146 }
147 formatter.write_str(", ")?;
148 if let Some(right) = &self.right_argument {
149 write!(formatter, "{right}")?;
150 }
151 formatter.write_str(") RESTRICT")
152 }
153}
154
155#[derive(Debug, Clone, PartialEq)]
156pub struct CreateOperatorClassStatement {
157 pub token: Token,
158 pub name: ObjectName,
159 pub input_type: ProceduralType,
160 pub access_method: IndexMethod,
161 pub extension_name: Identifier,
162 pub local_id: SmartString,
163}
164
165impl fmt::Display for CreateOperatorClassStatement {
166 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
167 write!(
168 formatter,
169 "CREATE OPERATOR CLASS {} FOR TYPE {} USING {} FROM EXTENSION {} AS '{}'",
170 self.name,
171 self.input_type,
172 self.access_method,
173 self.extension_name,
174 escape_sql_string(&self.local_id)
175 )
176 }
177}
178
179#[derive(Debug, Clone, PartialEq)]
180pub struct DropOperatorClassStatement {
181 pub token: Token,
182 pub name: ObjectName,
183 pub access_method: IndexMethod,
184 pub if_exists: bool,
185}
186
187#[derive(Debug, Clone, PartialEq)]
188pub struct CreatePlannerSupportStatement {
189 pub token: Token,
190 pub name: ObjectName,
191 pub function: RoutineSignatureSyntax,
192 pub extension_name: Identifier,
193 pub local_id: SmartString,
194}
195
196impl fmt::Display for CreatePlannerSupportStatement {
197 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
198 write!(
199 formatter,
200 "CREATE PLANNER SUPPORT {} FOR FUNCTION {} FROM EXTENSION {} AS '{}'",
201 self.name,
202 self.function,
203 self.extension_name,
204 escape_sql_string(&self.local_id)
205 )
206 }
207}
208
209#[derive(Debug, Clone, PartialEq)]
210pub struct DropPlannerSupportStatement {
211 pub token: Token,
212 pub name: ObjectName,
213 pub if_exists: bool,
214}
215
216impl fmt::Display for DropPlannerSupportStatement {
217 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
218 formatter.write_str("DROP PLANNER SUPPORT ")?;
219 if self.if_exists {
220 formatter.write_str("IF EXISTS ")?;
221 }
222 write!(formatter, "{} RESTRICT", self.name)
223 }
224}
225
226impl fmt::Display for DropOperatorClassStatement {
227 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
228 formatter.write_str("DROP OPERATOR CLASS ")?;
229 if self.if_exists {
230 formatter.write_str("IF EXISTS ")?;
231 }
232 write!(
233 formatter,
234 "{} USING {} RESTRICT",
235 self.name, self.access_method
236 )
237 }
238}
239
240impl fmt::Display for DropExternalTypeStatement {
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242 write!(f, "DROP TYPE ")?;
243 if self.if_exists {
244 write!(f, "IF EXISTS ")?;
245 }
246 write!(f, "{} RESTRICT", self.name)
247 }
248}
249
250#[derive(Debug, Clone, PartialEq)]
252pub struct CreateTableStatement {
253 pub token: Token,
254 pub table_name: Identifier,
255 pub if_not_exists: bool,
256 pub columns: Vec<ColumnDefinition>,
257 pub table_constraints: Vec<TableConstraint>,
259 pub as_select: Option<Box<SelectStatement>>,
261}
262
263impl fmt::Display for CreateTableStatement {
264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265 let mut result = String::from("CREATE TABLE ");
266 if self.if_not_exists {
267 result.push_str("IF NOT EXISTS ");
268 }
269 if let Some(ref select) = self.as_select {
270 result.push_str(&format!("{} AS {}", self.table_name, select));
271 return write!(f, "{}", result);
272 }
273 result.push_str(&format!("{} (", self.table_name));
274 let cols: Vec<String> = self.columns.iter().map(|c| c.to_string()).collect();
275 result.push_str(&cols.join(", "));
276 if !self.table_constraints.is_empty() {
277 let constraints: Vec<String> = self
278 .table_constraints
279 .iter()
280 .map(|c| c.to_string())
281 .collect();
282 result.push_str(", ");
283 result.push_str(&constraints.join(", "));
284 }
285 result.push(')');
286 write!(f, "{}", result)
287 }
288}
289
290#[derive(Debug, Clone, PartialEq)]
292pub struct ColumnDefinition {
293 pub name: Identifier,
294 pub data_type: SmartString,
295 pub constraints: Vec<ColumnConstraint>,
296}
297
298impl fmt::Display for ColumnDefinition {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 let mut result = format!("{} {}", self.name, self.data_type);
301 for constraint in &self.constraints {
302 result.push_str(&format!(" {}", constraint));
303 }
304 write!(f, "{}", result)
305 }
306}
307
308#[derive(Debug, Clone, PartialEq)]
310pub enum ColumnConstraint {
311 NotNull,
312 PrimaryKey,
313 Unique,
314 AutoIncrement,
315 Default(Expression),
316 Check(Expression),
317 References {
318 table: Identifier,
319 column: Option<Identifier>,
320 on_delete: ForeignKeyAction,
321 on_update: ForeignKeyAction,
322 },
323}
324
325impl fmt::Display for ColumnConstraint {
326 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
327 match self {
328 ColumnConstraint::NotNull => write!(f, "NOT NULL"),
329 ColumnConstraint::PrimaryKey => write!(f, "PRIMARY KEY"),
330 ColumnConstraint::Unique => write!(f, "UNIQUE"),
331 ColumnConstraint::AutoIncrement => write!(f, "AUTO_INCREMENT"),
332 ColumnConstraint::Default(expr) => write!(f, "DEFAULT {}", expr),
333 ColumnConstraint::Check(expr) => write!(f, "CHECK ({})", expr),
334 ColumnConstraint::References {
335 table,
336 column,
337 on_delete,
338 on_update,
339 } => {
340 write!(f, "REFERENCES {}", table)?;
341 if let Some(col) = column {
342 write!(f, "({})", col)?;
343 }
344 if *on_delete != ForeignKeyAction::Restrict {
345 write!(f, " ON DELETE {}", on_delete)?;
346 }
347 if *on_update != ForeignKeyAction::Restrict {
348 write!(f, " ON UPDATE {}", on_update)?;
349 }
350 Ok(())
351 }
352 }
353 }
354}
355
356#[derive(Debug, Clone, PartialEq)]
358pub enum TableConstraint {
359 Unique(Vec<Identifier>),
361 Check(Box<Expression>),
363 PrimaryKey(Vec<Identifier>),
365 ForeignKey(Box<ForeignKeyTableConstraint>),
368}
369
370#[derive(Debug, Clone, PartialEq)]
372pub struct ForeignKeyTableConstraint {
373 pub column: Identifier,
374 pub ref_table: Identifier,
375 pub ref_column: Option<Identifier>,
376 pub on_delete: ForeignKeyAction,
377 pub on_update: ForeignKeyAction,
378}
379
380impl fmt::Display for TableConstraint {
381 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
382 match self {
383 TableConstraint::Unique(cols) => {
384 let col_names: Vec<&str> = cols.iter().map(|c| c.value.as_str()).collect();
385 write!(f, "UNIQUE({})", col_names.join(", "))
386 }
387 TableConstraint::Check(expr) => write!(f, "CHECK({})", expr),
388 TableConstraint::PrimaryKey(cols) => {
389 let col_names: Vec<&str> = cols.iter().map(|c| c.value.as_str()).collect();
390 write!(f, "PRIMARY KEY({})", col_names.join(", "))
391 }
392 TableConstraint::ForeignKey(fk) => {
393 write!(f, "FOREIGN KEY({}) REFERENCES {}", fk.column, fk.ref_table)?;
394 if let Some(ref col) = fk.ref_column {
395 write!(f, "({})", col)?;
396 }
397 if fk.on_delete != ForeignKeyAction::Restrict {
398 write!(f, " ON DELETE {}", fk.on_delete)?;
399 }
400 if fk.on_update != ForeignKeyAction::Restrict {
401 write!(f, " ON UPDATE {}", fk.on_update)?;
402 }
403 Ok(())
404 }
405 }
406 }
407}
408
409#[derive(Debug, Clone, PartialEq)]
411pub enum ColumnOrConstraint {
412 Column(ColumnDefinition),
413 Constraint(TableConstraint),
414}
415
416#[derive(Debug, Clone, PartialEq)]
418pub struct DropTableStatement {
419 pub token: Token,
420 pub table_name: Identifier,
421 pub if_exists: bool,
422}
423
424impl fmt::Display for DropTableStatement {
425 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
426 let mut result = String::from("DROP TABLE ");
427 if self.if_exists {
428 result.push_str("IF EXISTS ");
429 }
430 result.push_str(&self.table_name.to_string());
431 write!(f, "{}", result)
432 }
433}
434
435#[derive(Debug, Clone, PartialEq)]
437pub struct TruncateStatement {
438 pub token: Token,
439 pub table_name: Identifier,
440}
441
442impl fmt::Display for TruncateStatement {
443 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
444 write!(f, "TRUNCATE TABLE {}", self.table_name)
445 }
446}
447
448#[derive(Debug, Clone, PartialEq)]
450pub struct VacuumStatement {
451 pub token: Token,
452 pub table_name: Option<Identifier>,
453}
454
455impl fmt::Display for VacuumStatement {
456 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
457 if let Some(ref table_name) = self.table_name {
458 write!(f, "VACUUM {}", table_name)
459 } else {
460 write!(f, "VACUUM")
461 }
462 }
463}
464
465#[derive(Debug, Clone, Copy, PartialEq, Eq)]
467pub enum CopyFormat {
468 Csv,
469 Json,
470}
471
472impl fmt::Display for CopyFormat {
473 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
474 match self {
475 CopyFormat::Csv => write!(f, "CSV"),
476 CopyFormat::Json => write!(f, "JSON"),
477 }
478 }
479}
480
481#[derive(Debug, Clone, PartialEq)]
483pub struct CopyStatement {
484 pub token: Token,
485 pub table_name: Identifier,
486 pub columns: Vec<Identifier>,
487 pub file_path: String,
488 pub format: CopyFormat,
489 pub header: bool,
490 pub delimiter: u8,
491 pub null_string: Option<String>,
492}
493
494impl fmt::Display for CopyStatement {
495 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
496 write!(f, "COPY {}", self.table_name)?;
497 if !self.columns.is_empty() {
498 write!(f, " (")?;
499 for (i, col) in self.columns.iter().enumerate() {
500 if i > 0 {
501 write!(f, ", ")?;
502 }
503 write!(f, "{}", col)?;
504 }
505 write!(f, ")")?;
506 }
507 write!(f, " FROM '{}'", escape_sql_string(&self.file_path))?;
508 write!(f, " WITH (FORMAT {}", self.format)?;
509 if self.format == CopyFormat::Csv {
510 if self.header {
511 write!(f, ", HEADER true")?;
512 }
513 if self.delimiter != b',' {
514 write!(
515 f,
516 ", DELIMITER '{}'",
517 escape_sql_string(&(self.delimiter as char).to_string())
518 )?;
519 }
520 }
521 if let Some(ref ns) = self.null_string {
522 write!(f, ", NULL '{}'", escape_sql_string(ns))?;
523 }
524 write!(f, ")")
525 }
526}
527
528#[derive(Debug, Clone, Copy, PartialEq, Eq)]
530pub enum AlterTableOperation {
531 AddColumn,
532 AddConstraint,
533 DropColumn,
534 DropConstraint,
535 RenameColumn,
536 ModifyColumn,
537 RenameTable,
538}
539
540#[derive(Debug, Clone, PartialEq)]
542pub struct AlterTableStatement {
543 pub token: Token,
544 pub table_name: Identifier,
545 pub operation: AlterTableOperation,
546 pub column_def: Option<ColumnDefinition>,
547 pub table_constraint: Option<TableConstraint>,
548 pub column_name: Option<Identifier>,
549 pub constraint_name: Option<Identifier>,
550 pub if_exists: bool,
551 pub new_column_name: Option<Identifier>,
552 pub new_table_name: Option<Identifier>,
553}
554
555impl fmt::Display for AlterTableStatement {
556 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
557 let mut result = format!("ALTER TABLE {} ", self.table_name);
558 match self.operation {
559 AlterTableOperation::AddColumn => {
560 if let Some(ref col) = self.column_def {
561 result.push_str(&format!("ADD COLUMN {}", col));
562 }
563 }
564 AlterTableOperation::AddConstraint => {
565 if let Some(ref constraint) = self.table_constraint {
566 result.push_str(&format!("ADD CONSTRAINT {}", constraint));
567 }
568 }
569 AlterTableOperation::DropColumn => {
570 if let Some(ref name) = self.column_name {
571 result.push_str(&format!("DROP COLUMN {}", name));
572 }
573 }
574 AlterTableOperation::DropConstraint => {
575 result.push_str("DROP CONSTRAINT ");
576 if self.if_exists {
577 result.push_str("IF EXISTS ");
578 }
579 if let Some(ref name) = self.constraint_name {
580 result.push_str(&name.to_string());
581 }
582 }
583 AlterTableOperation::RenameColumn => {
584 if let (Some(ref old), Some(ref new)) = (&self.column_name, &self.new_column_name) {
585 result.push_str(&format!("RENAME COLUMN {} TO {}", old, new));
586 }
587 }
588 AlterTableOperation::ModifyColumn => {
589 if let Some(ref col) = self.column_def {
590 result.push_str(&format!("MODIFY COLUMN {}", col));
591 }
592 }
593 AlterTableOperation::RenameTable => {
594 if let Some(ref name) = self.new_table_name {
595 result.push_str(&format!("RENAME TO {}", name));
596 }
597 }
598 }
599 write!(f, "{}", result)
600 }
601}
602
603#[derive(Debug, Clone, PartialEq)]
605pub struct AlterIndexStatement {
606 pub token: Token,
607 pub index_name: Identifier,
608 pub new_index_name: Identifier,
609}
610
611impl fmt::Display for AlterIndexStatement {
612 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
613 write!(
614 f,
615 "ALTER INDEX {} RENAME TO {}",
616 self.index_name, self.new_index_name
617 )
618 }
619}
620
621#[derive(Debug, Clone, Copy, PartialEq, Eq)]
623pub enum IndexMethod {
624 BTree,
626 Hash,
628 Bitmap,
630 Hnsw,
632}
633
634impl fmt::Display for IndexMethod {
635 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
636 match self {
637 IndexMethod::BTree => write!(f, "BTREE"),
638 IndexMethod::Hash => write!(f, "HASH"),
639 IndexMethod::Bitmap => write!(f, "BITMAP"),
640 IndexMethod::Hnsw => write!(f, "HNSW"),
641 }
642 }
643}
644
645#[derive(Debug, Clone, PartialEq)]
647pub struct CreateIndexStatement {
648 pub token: Token,
649 pub index_name: Identifier,
650 pub table_name: Identifier,
651 pub columns: Vec<Identifier>,
652 pub is_unique: bool,
653 pub if_not_exists: bool,
654 pub index_method: Option<IndexMethod>,
656 pub options: Vec<(String, Expression)>,
658 pub where_clause: Option<Box<Expression>>,
660 pub operator_class: Option<ObjectName>,
662}
663
664impl fmt::Display for CreateIndexStatement {
665 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
666 let mut result = String::from("CREATE ");
667 if self.is_unique {
668 result.push_str("UNIQUE ");
669 }
670 result.push_str("INDEX ");
671 if self.if_not_exists {
672 result.push_str("IF NOT EXISTS ");
673 }
674 result.push_str(&format!("{} ON {} (", self.index_name, self.table_name));
675 let mut cols: Vec<String> = self.columns.iter().map(|c| c.to_string()).collect();
676 if let (Some(first), Some(operator_class)) = (cols.first_mut(), &self.operator_class) {
677 first.push(' ');
678 first.push_str(&operator_class.to_string());
679 }
680 result.push_str(&cols.join(", "));
681 result.push(')');
682 if let Some(method) = &self.index_method {
683 result.push_str(&format!(" USING {}", method));
684 }
685 if !self.options.is_empty() {
686 result.push_str(" WITH (");
687 for (i, (key, value)) in self.options.iter().enumerate() {
688 if i > 0 {
689 result.push_str(", ");
690 }
691 result.push_str(&format!("{} = {}", key, value));
692 }
693 result.push(')');
694 }
695 if let Some(ref where_clause) = self.where_clause {
696 result.push_str(&format!(" WHERE {}", where_clause));
697 }
698 write!(f, "{}", result)
699 }
700}
701
702#[derive(Debug, Clone, PartialEq)]
704pub struct DropIndexStatement {
705 pub token: Token,
706 pub index_name: Identifier,
707 pub table_name: Option<Identifier>,
708 pub if_exists: bool,
709}
710
711impl fmt::Display for DropIndexStatement {
712 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
713 let mut result = String::from("DROP INDEX ");
714 if self.if_exists {
715 result.push_str("IF EXISTS ");
716 }
717 result.push_str(&self.index_name.to_string());
718 if let Some(ref table) = self.table_name {
719 result.push_str(&format!(" ON {}", table));
720 }
721 write!(f, "{}", result)
722 }
723}
724
725#[derive(Debug, Clone, PartialEq)]
727pub struct CreateViewStatement {
728 pub token: Token,
729 pub view_name: Identifier,
730 pub query: Box<SelectStatement>,
731 pub if_not_exists: bool,
732}
733
734impl fmt::Display for CreateViewStatement {
735 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
736 let mut result = String::from("CREATE VIEW ");
737 if self.if_not_exists {
738 result.push_str("IF NOT EXISTS ");
739 }
740 result.push_str(&format!("{} AS {}", self.view_name, self.query));
741 write!(f, "{}", result)
742 }
743}
744
745#[derive(Debug, Clone, PartialEq)]
747pub struct DropViewStatement {
748 pub token: Token,
749 pub view_name: Identifier,
750 pub if_exists: bool,
751}
752
753impl fmt::Display for DropViewStatement {
754 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
755 let mut result = String::from("DROP VIEW ");
756 if self.if_exists {
757 result.push_str("IF EXISTS ");
758 }
759 result.push_str(&self.view_name.to_string());
760 write!(f, "{}", result)
761 }
762}