Skip to content

Commit eff0f62

Browse files
committed
Generalized support for table options
create table parsing - comment parsing to generic parameter parsing create table parsing - unify the different parameter options into the CreateTableOptions enum create table parsing - consolidate SqlOption::Union & SqlOption::TableEngine into SqlOption::NamedParenthesizedList
1 parent 5b9fa35 commit eff0f62

16 files changed

+750
-1749
lines changed

src/ast/dml.rs

Lines changed: 19 additions & 239 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,15 @@ use serde::{Deserialize, Serialize};
2929
#[cfg(feature = "visitor")]
3030
use sqlparser_derive::{Visit, VisitMut};
3131

32-
use crate::parser::{
33-
Compression, DelayKeyWrite, DirectoryOption, Encryption, InsertMethod, OptionState, RowFormat,
34-
StorageType, TablespaceOption,
35-
};
36-
3732
pub use super::ddl::{ColumnDef, TableConstraint};
3833

3934
use super::{
4035
display_comma_separated, display_separated, query::InputFormatClause, Assignment, ClusteredBy,
41-
CommentDef, Expr, FileFormat, FromTable, HiveDistributionStyle, HiveFormat, HiveIOFormat,
42-
HiveRowFormat, Ident, IndexType, InsertAliases, MysqlInsertPriority, ObjectName, OnCommit,
43-
OnInsert, OneOrManyWithParens, OrderByExpr, Query, RowAccessPolicy, SelectItem, Setting,
44-
SqlOption, SqliteOnConflict, StorageSerializationPolicy, TableEngine, TableObject,
45-
TableWithJoins, Tag, WrappedCollection,
36+
CommentDef, CreateTableOptions, Expr, FileFormat, FromTable, HiveDistributionStyle, HiveFormat,
37+
HiveIOFormat, HiveRowFormat, Ident, IndexType, InsertAliases, MysqlInsertPriority, ObjectName,
38+
OnCommit, OnInsert, OneOrManyWithParens, OrderByExpr, Query, RowAccessPolicy, SelectItem,
39+
Setting, SqliteOnConflict, StorageSerializationPolicy, TableObject, TableWithJoins, Tag,
40+
WrappedCollection,
4641
};
4742

4843
/// Index column type.
@@ -151,43 +146,17 @@ pub struct CreateTable {
151146
pub constraints: Vec<TableConstraint>,
152147
pub hive_distribution: HiveDistributionStyle,
153148
pub hive_formats: Option<HiveFormat>,
154-
pub table_properties: Vec<SqlOption>,
155-
pub with_options: Vec<SqlOption>,
149+
pub table_options: CreateTableOptions,
156150
pub file_format: Option<FileFormat>,
157151
pub location: Option<String>,
158152
pub query: Option<Box<Query>>,
159153
pub without_rowid: bool,
160154
pub like: Option<ObjectName>,
161155
pub clone: Option<ObjectName>,
162-
pub engine: Option<TableEngine>,
163-
pub comment: Option<CommentDef>,
164-
pub auto_increment_offset: Option<u32>,
165-
pub key_block_size: Option<u32>,
166-
pub max_rows: Option<u32>,
167-
pub min_rows: Option<u32>,
168-
pub autoextend_size: Option<u32>,
169-
pub avg_row_length: Option<u32>,
170-
pub checksum: Option<bool>,
171-
pub connection: Option<String>,
172-
pub engine_attribute: Option<String>,
173-
pub password: Option<String>,
174-
pub secondary_engine_attribute: Option<String>,
175-
pub tablespace_option: Option<TablespaceOption>,
176-
pub row_format: Option<RowFormat>,
177-
pub insert_method: Option<InsertMethod>,
178-
pub compression: Option<Compression>,
179-
pub delay_key_write: Option<DelayKeyWrite>,
180-
pub encryption: Option<Encryption>,
181-
pub pack_keys: Option<OptionState>,
182-
pub stats_auto_recalc: Option<OptionState>,
183-
pub stats_persistent: Option<OptionState>,
184-
pub stats_sample_pages: Option<u32>,
185-
pub start_transaction: Option<bool>,
186-
pub union_tables: Option<Vec<String>>,
187-
pub data_directory: Option<DirectoryOption>,
188-
pub index_directory: Option<DirectoryOption>,
189-
pub default_charset: Option<String>,
190-
pub collation: Option<String>,
156+
// For Hive dialect, the table comment is after the column definitions without `=`,
157+
// so we need to add an extra variant to allow to identify this case when displaying.
158+
// [Hive](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable)
159+
pub comment_after_column_def: Option<CommentDef>,
191160
pub on_commit: Option<OnCommit>,
192161
/// ClickHouse "ON CLUSTER" clause:
193162
/// <https://clickhouse.com/docs/en/sql-reference/distributed-ddl/>
@@ -208,9 +177,6 @@ pub struct CreateTable {
208177
/// Hive: Table clustering column list.
209178
/// <https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable>
210179
pub clustered_by: Option<ClusteredBy>,
211-
/// BigQuery: Table options list.
212-
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
213-
pub options: Option<Vec<SqlOption>>,
214180
/// Postgres `INHERITs` clause, which contains the list of tables from which
215181
/// the new table inherits.
216182
/// <https://www.postgresql.org/docs/current/ddl-inherit.html>
@@ -311,7 +277,7 @@ impl Display for CreateTable {
311277

312278
// Hive table comment should be after column definitions, please refer to:
313279
// [Hive](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable)
314-
if let Some(CommentDef::AfterColumnDefsWithoutEq(comment)) = &self.comment {
280+
if let Some(comment) = &self.comment_after_column_def {
315281
write!(f, " COMMENT '{comment}'")?;
316282
}
317283

@@ -404,35 +370,14 @@ impl Display for CreateTable {
404370
}
405371
write!(f, " LOCATION '{}'", self.location.as_ref().unwrap())?;
406372
}
407-
if !self.table_properties.is_empty() {
408-
write!(
409-
f,
410-
" TBLPROPERTIES ({})",
411-
display_comma_separated(&self.table_properties)
412-
)?;
413-
}
414-
if !self.with_options.is_empty() {
415-
write!(f, " WITH ({})", display_comma_separated(&self.with_options))?;
416-
}
417-
if let Some(engine) = &self.engine {
418-
write!(f, " ENGINE={engine}")?;
419-
}
420-
if let Some(comment_def) = &self.comment {
421-
match comment_def {
422-
CommentDef::WithEq(comment) => {
423-
write!(f, " COMMENT = '{comment}'")?;
424-
}
425-
CommentDef::WithoutEq(comment) => {
426-
write!(f, " COMMENT '{comment}'")?;
427-
}
428-
// For CommentDef::AfterColumnDefsWithoutEq will be displayed after column definition
429-
CommentDef::AfterColumnDefsWithoutEq(_) => (),
430-
}
431-
}
432373

433-
if let Some(auto_increment_offset) = self.auto_increment_offset {
434-
write!(f, " AUTO_INCREMENT={auto_increment_offset}")?;
374+
match &self.table_options {
375+
options @ CreateTableOptions::With(_)
376+
| options @ CreateTableOptions::Plain(_)
377+
| options @ CreateTableOptions::TableProperties(_) => write!(f, " {}", options)?,
378+
_ => (),
435379
}
380+
436381
if let Some(primary_key) = &self.primary_key {
437382
write!(f, " PRIMARY KEY {}", primary_key)?;
438383
}
@@ -448,15 +393,9 @@ impl Display for CreateTable {
448393
if let Some(cluster_by) = self.cluster_by.as_ref() {
449394
write!(f, " CLUSTER BY {cluster_by}")?;
450395
}
451-
452-
if let Some(options) = self.options.as_ref() {
453-
write!(
454-
f,
455-
" OPTIONS({})",
456-
display_comma_separated(options.as_slice())
457-
)?;
396+
if let options @ CreateTableOptions::Options(_) = &self.table_options {
397+
write!(f, " {}", options)?;
458398
}
459-
460399
if let Some(external_volume) = self.external_volume.as_ref() {
461400
write!(f, " EXTERNAL_VOLUME = '{external_volume}'")?;
462401
}
@@ -532,165 +471,6 @@ impl Display for CreateTable {
532471
write!(f, " WITH TAG ({})", display_comma_separated(tag.as_slice()))?;
533472
}
534473

535-
if let Some(default_charset) = &self.default_charset {
536-
write!(f, " DEFAULT CHARSET={default_charset}")?;
537-
}
538-
if let Some(collation) = &self.collation {
539-
write!(f, " COLLATE={collation}")?;
540-
}
541-
542-
if let Some(insert_method) = &self.insert_method {
543-
match insert_method {
544-
InsertMethod::No => write!(f, " INSERT_METHOD=NO")?,
545-
InsertMethod::First => write!(f, " INSERT_METHOD=FIRST")?,
546-
InsertMethod::Last => write!(f, " INSERT_METHOD=LAST")?,
547-
}
548-
}
549-
550-
if let Some(key_block_size) = self.key_block_size {
551-
write!(f, " KEY_BLOCK_SIZE={key_block_size}")?;
552-
}
553-
554-
if let Some(row_format) = &self.row_format {
555-
match row_format {
556-
RowFormat::Default => write!(f, " ROW_FORMAT=DEFAULT")?,
557-
RowFormat::Dynamic => write!(f, " ROW_FORMAT=DYNAMIC")?,
558-
RowFormat::Fixed => write!(f, " ROW_FORMAT=FIXED")?,
559-
RowFormat::Compressed => write!(f, " ROW_FORMAT=COMPRESSED")?,
560-
RowFormat::Redundant => write!(f, " ROW_FORMAT=REDUNDANT")?,
561-
RowFormat::Compact => write!(f, " ROW_FORMAT=COMPACT")?,
562-
}
563-
}
564-
565-
if let Some(data_dir) = &self.data_directory {
566-
write!(f, " DATA DIRECTORY='{}'", data_dir.path)?;
567-
}
568-
569-
if let Some(index_dir) = &self.index_directory {
570-
write!(f, " INDEX DIRECTORY='{}'", index_dir.path)?;
571-
}
572-
573-
if let Some(pack_keys) = &self.pack_keys {
574-
match pack_keys {
575-
OptionState::Default => write!(f, " PACK_KEYS=DEFAULT")?,
576-
OptionState::One => write!(f, " PACK_KEYS=1")?,
577-
OptionState::Zero => write!(f, " PACK_KEYS=0")?,
578-
}
579-
}
580-
581-
if let Some(stats_auto_recalc) = &self.stats_auto_recalc {
582-
match stats_auto_recalc {
583-
OptionState::Default => write!(f, " STATS_AUTO_RECALC=DEFAULT")?,
584-
OptionState::One => write!(f, " STATS_AUTO_RECALC=1")?,
585-
OptionState::Zero => write!(f, " STATS_AUTO_RECALC=0")?,
586-
}
587-
}
588-
589-
if let Some(stats_persistent) = &self.stats_persistent {
590-
match stats_persistent {
591-
OptionState::Default => write!(f, " STATS_PERSISTENT=DEFAULT")?,
592-
OptionState::One => write!(f, " STATS_PERSISTENT=1")?,
593-
OptionState::Zero => write!(f, " STATS_PERSISTENT=0")?,
594-
}
595-
}
596-
597-
if let Some(stats_sample_pages) = self.stats_sample_pages {
598-
write!(f, " STATS_SAMPLE_PAGES={stats_sample_pages}")?;
599-
}
600-
601-
if let Some(delay_key_write) = &self.delay_key_write {
602-
match delay_key_write {
603-
DelayKeyWrite::Enabled => write!(f, " DELAY_KEY_WRITE=1")?,
604-
DelayKeyWrite::Disabled => write!(f, " DELAY_KEY_WRITE=0")?,
605-
}
606-
}
607-
608-
if let Some(compression) = &self.compression {
609-
match compression {
610-
Compression::Lz4 => write!(f, " COMPRESSION=LZ4")?,
611-
Compression::Zlib => write!(f, " COMPRESSION=ZLIB")?,
612-
Compression::None => write!(f, " COMPRESSION=NONE")?,
613-
}
614-
}
615-
616-
if let Some(encryption) = &self.encryption {
617-
match encryption {
618-
Encryption::Yes => write!(f, " ENCRYPTION='Y'")?,
619-
Encryption::No => write!(f, " ENCRYPTION='N'")?,
620-
}
621-
}
622-
623-
if let Some(max_rows) = &self.max_rows {
624-
write!(f, " MAX_ROWS={}", max_rows)?;
625-
}
626-
627-
if let Some(min_rows) = &self.min_rows {
628-
write!(f, " MIN_ROWS={}", min_rows)?;
629-
}
630-
631-
if let Some(autoextend_size) = &self.autoextend_size {
632-
write!(f, " AUTOEXTEND_SIZE={}", autoextend_size)?;
633-
}
634-
635-
if let Some(avg_row_length) = &self.avg_row_length {
636-
write!(f, " AVG_ROW_LENGTH={}", avg_row_length)?;
637-
}
638-
639-
if let Some(checksum) = &self.checksum {
640-
match checksum {
641-
true => write!(f, " CHECKSUM=1")?,
642-
false => write!(f, " CHECKSUM=0")?,
643-
}
644-
}
645-
646-
if let Some(connection) = &self.connection {
647-
write!(f, " CONNECTION='{}'", connection)?;
648-
}
649-
650-
if let Some(engine_attribute) = &self.engine_attribute {
651-
write!(f, " ENGINE_ATTRIBUTE='{}'", engine_attribute)?;
652-
}
653-
654-
if let Some(password) = &self.password {
655-
write!(f, " PASSWORD='{}'", password)?;
656-
}
657-
658-
if let Some(secondary_engine_attribute) = &self.secondary_engine_attribute {
659-
write!(
660-
f,
661-
" SECONDARY_ENGINE_ATTRIBUTE='{}'",
662-
secondary_engine_attribute
663-
)?;
664-
}
665-
666-
if self.start_transaction.unwrap_or(false) {
667-
write!(f, " START TRANSACTION")?;
668-
}
669-
670-
if let Some(tablespace_option) = &self.tablespace_option {
671-
write!(f, " TABLESPACE {}", tablespace_option.name)?;
672-
if let Some(storage) = &tablespace_option.storage {
673-
match storage {
674-
StorageType::Disk => write!(f, " STORAGE DISK")?,
675-
StorageType::Memory => write!(f, " STORAGE MEMORY")?,
676-
}
677-
}
678-
}
679-
680-
if let Some(union_tables) = &self.union_tables {
681-
if !union_tables.is_empty() {
682-
write!(
683-
f,
684-
" UNION=({})",
685-
union_tables
686-
.iter()
687-
.map(|table| table.to_string())
688-
.collect::<Vec<String>>()
689-
.join(", ")
690-
)?;
691-
}
692-
}
693-
694474
if self.on_commit.is_some() {
695475
let on_commit = match self.on_commit {
696476
Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS",

0 commit comments

Comments
 (0)