@@ -29,20 +29,15 @@ use serde::{Deserialize, Serialize};
2929#[ cfg( feature = "visitor" ) ]
3030use sqlparser_derive:: { Visit , VisitMut } ;
3131
32- use crate :: parser:: {
33- Compression , DelayKeyWrite , DirectoryOption , Encryption , InsertMethod , OptionState , RowFormat ,
34- StorageType , TablespaceOption ,
35- } ;
36-
3732pub use super :: ddl:: { ColumnDef , TableConstraint } ;
3833
3934use 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