diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index 45ddc1e9f..13cddf566 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -20,7 +20,7 @@ use core::fmt; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use sqlparser::ast::{Value, WithSpan}; +use sqlparser::ast::{SqlOption, Value, WithSpan}; #[cfg(feature = "visitor")] use sqlparser_derive::{Visit, VisitMut}; @@ -551,6 +551,7 @@ pub struct ColumnDef { pub collation: Option, pub codec: Option>, pub options: Vec, + pub column_options: Vec, } impl fmt::Display for ColumnDef { @@ -565,6 +566,13 @@ impl fmt::Display for ColumnDef { for option in &self.options { write!(f, " {option}")?; } + if !self.column_options.is_empty() { + write!( + f, + " OPTIONS({})", + display_comma_separated(&self.column_options) + )?; + } Ok(()) } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 7039e812c..6bed54ea2 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -4303,12 +4303,16 @@ impl<'a> Parser<'a> { break; }; } + + let column_options = self.parse_options(Keyword::OPTIONS)?; + Ok(ColumnDef { name, data_type, collation, codec, options, + column_options, }) } diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs index db544864c..882c487af 100644 --- a/tests/sqlparser_bigquery.rs +++ b/tests/sqlparser_bigquery.rs @@ -113,6 +113,7 @@ fn parse_nested_data_types() { collation: None, codec: None, options: vec![], + column_options: vec![] }, ColumnDef { name: Ident::new("y").empty_span(), @@ -125,6 +126,7 @@ fn parse_nested_data_types() { collation: None, codec: None, options: vec![], + column_options: vec![] }, ] ); @@ -1276,3 +1278,10 @@ fn test_create_external_table_with_options() { r#"CREATE EXTERNAL TABLE mytable (id INT64, timestamp TIMESTAMP) OPTIONS (sheet_range = "synq", skip_leading_rows = 1, format = "GOOGLE_SHEETS", uris = ["https://docs.google.com/spreadsheets/d/1g3xwWi1r-Ln2VVwv4mswwmqyfMeoJglv-MS80ywASGI/edit#gid=0"])"#, ); } + +#[test] +fn test_create_table_field_options() { + bigquery().verified_stmt( + "CREATE TABLE `pr`.`ts`.`salesforce_accounts` (account_name STRING OPTIONS(description = \"Account name\", label = \"dev\"))", + ); +} diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 140973770..4c41ce0f8 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -2481,6 +2481,7 @@ fn parse_create_table() { name: None, option: ColumnOption::NotNull, }], + column_options: vec![], }, ColumnDef { name: Ident::new("lat").empty_span(), @@ -2491,6 +2492,7 @@ fn parse_create_table() { name: None, option: ColumnOption::Null, }], + column_options: vec![], }, ColumnDef { name: Ident::new("lng").empty_span(), @@ -2498,6 +2500,7 @@ fn parse_create_table() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("constrained").empty_span(), @@ -2526,6 +2529,7 @@ fn parse_create_table() { option: ColumnOption::Check(verified_expr("constrained > 0")), }, ], + column_options: vec![], }, ColumnDef { name: Ident::new("ref").empty_span(), @@ -2544,6 +2548,7 @@ fn parse_create_table() { on_update: None, }, }], + column_options: vec![], }, ColumnDef { name: Ident::new("ref2").empty_span(), @@ -2559,6 +2564,7 @@ fn parse_create_table() { on_update: Some(ReferentialAction::NoAction), }, },], + column_options: vec![], }, ] ); @@ -2676,6 +2682,7 @@ fn parse_create_table_hive_array() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("val").empty_span(), @@ -2683,6 +2690,7 @@ fn parse_create_table_hive_array() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ], ) @@ -3046,6 +3054,7 @@ fn parse_create_external_table() { name: None, option: ColumnOption::NotNull, }], + column_options: vec![], }, ColumnDef { name: Ident::new("lat").empty_span(), @@ -3056,6 +3065,7 @@ fn parse_create_external_table() { name: None, option: ColumnOption::Null, }], + column_options: vec![], }, ColumnDef { name: Ident::new("lng").empty_span(), @@ -3063,6 +3073,7 @@ fn parse_create_external_table() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ] ); @@ -3120,6 +3131,7 @@ fn parse_create_or_replace_external_table() { name: None, option: ColumnOption::NotNull, }], + column_options: vec![], },] ); assert!(constraints.is_empty()); diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index 3638c4c0d..7f46acde8 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -290,6 +290,7 @@ fn parse_create_table_auto_increment() { )]), }, ], + column_options: vec![], }], columns ); @@ -338,6 +339,7 @@ fn parse_create_table_unique_key() { )]), }, ], + column_options: vec![], }, ColumnDef { name: Ident::new("bar").empty_span(), @@ -348,6 +350,7 @@ fn parse_create_table_unique_key() { name: None, option: ColumnOption::NotNull, },], + column_options: vec![], }, ], columns @@ -412,6 +415,7 @@ fn parse_create_table_set_enum() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("baz").empty_span(), @@ -419,6 +423,7 @@ fn parse_create_table_set_enum() { collation: None, codec: None, options: vec![], + column_options: vec![], } ], columns @@ -447,6 +452,7 @@ fn parse_create_table_engine_default_charset() { collation: None, codec: None, options: vec![], + column_options: vec![], },], columns ); @@ -475,6 +481,7 @@ fn parse_create_table_collate() { collation: None, codec: None, options: vec![], + column_options: vec![], },], columns ); @@ -508,6 +515,7 @@ fn parse_create_table_comment_character_set() { option: ColumnOption::Comment("comment".to_string()) } ], + column_options: vec![], },], columns ); @@ -532,6 +540,7 @@ fn parse_quote_identifiers() { name: None, option: ColumnOption::Unique { is_primary: true }, }], + column_options: vec![], }], columns ); @@ -885,6 +894,7 @@ fn parse_create_table_with_minimum_display_width() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("bar_smallint").empty_span(), @@ -892,6 +902,7 @@ fn parse_create_table_with_minimum_display_width() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("bar_mediumint").empty_span(), @@ -899,6 +910,7 @@ fn parse_create_table_with_minimum_display_width() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("bar_int").empty_span(), @@ -906,6 +918,7 @@ fn parse_create_table_with_minimum_display_width() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("bar_bigint").empty_span(), @@ -913,6 +926,7 @@ fn parse_create_table_with_minimum_display_width() { collation: None, codec: None, options: vec![], + column_options: vec![], } ], columns @@ -936,6 +950,7 @@ fn parse_create_table_unsigned() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("bar_smallint").empty_span(), @@ -943,6 +958,7 @@ fn parse_create_table_unsigned() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("bar_mediumint").empty_span(), @@ -950,6 +966,7 @@ fn parse_create_table_unsigned() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("bar_int").empty_span(), @@ -957,6 +974,7 @@ fn parse_create_table_unsigned() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("bar_bigint").empty_span(), @@ -964,6 +982,7 @@ fn parse_create_table_unsigned() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ], columns @@ -1570,6 +1589,7 @@ fn parse_table_colum_option_on_update() { within_group: None, })), },], + column_options: vec![], }], columns ); diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index f95586075..6f309fd30 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -338,6 +338,7 @@ fn parse_create_table_with_defaults() { pg().verified_expr("nextval(public.customer_customer_id_seq)") ) }], + column_options: vec![], }, ColumnDef { name: Ident::new("store_id").empty_span(), @@ -348,6 +349,7 @@ fn parse_create_table_with_defaults() { name: None, option: ColumnOption::NotNull, }], + column_options: vec![], }, ColumnDef { name: Ident::new("first_name").empty_span(), @@ -363,6 +365,7 @@ fn parse_create_table_with_defaults() { name: None, option: ColumnOption::NotNull, }], + column_options: vec![], }, ColumnDef { name: Ident::new("last_name").empty_span(), @@ -378,6 +381,7 @@ fn parse_create_table_with_defaults() { name: None, option: ColumnOption::NotNull, }], + column_options: vec![], }, ColumnDef { name: Ident::new("email").empty_span(), @@ -390,6 +394,7 @@ fn parse_create_table_with_defaults() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("address_id").empty_span(), @@ -400,6 +405,7 @@ fn parse_create_table_with_defaults() { name: None, option: ColumnOption::NotNull }], + column_options: vec![], }, ColumnDef { name: Ident::new("activebool").empty_span(), @@ -416,6 +422,7 @@ fn parse_create_table_with_defaults() { option: ColumnOption::NotNull, } ], + column_options: vec![], }, ColumnDef { name: Ident::new("create_date").empty_span(), @@ -434,6 +441,7 @@ fn parse_create_table_with_defaults() { option: ColumnOption::NotNull, } ], + column_options: vec![], }, ColumnDef { name: Ident::new("last_update").empty_span(), @@ -450,6 +458,7 @@ fn parse_create_table_with_defaults() { option: ColumnOption::NotNull, } ], + column_options: vec![], }, ColumnDef { name: Ident::new("active").empty_span(), @@ -460,6 +469,7 @@ fn parse_create_table_with_defaults() { name: None, option: ColumnOption::NotNull }], + column_options: vec![], }, ] ); @@ -624,6 +634,7 @@ fn parse_alter_table_add_columns() { collation: None, codec: None, options: vec![], + column_options: vec![], }, }, AlterTableOperation::AddColumn { @@ -635,6 +646,7 @@ fn parse_alter_table_add_columns() { collation: None, codec: None, options: vec![], + column_options: vec![], }, }, ] @@ -3599,42 +3611,48 @@ fn parse_create_table_with_alias() { data_type: DataType::Int8(None), collation: None, codec: None, - options: vec![] + options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("int4_col").empty_span(), data_type: DataType::Int4(None), collation: None, codec: None, - options: vec![] + options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("int2_col").empty_span(), data_type: DataType::Int2(None), collation: None, codec: None, - options: vec![] + options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("float8_col").empty_span(), data_type: DataType::Float8, collation: None, codec: None, - options: vec![] + options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("float4_col").empty_span(), data_type: DataType::Float4, collation: None, codec: None, - options: vec![] + options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::new("bool_col").empty_span(), data_type: DataType::Bool, collation: None, codec: None, - options: vec![] + options: vec![], + column_options: vec![], }, ] ); diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs index 47b87f054..38ed6465d 100644 --- a/tests/sqlparser_sqlite.rs +++ b/tests/sqlparser_sqlite.rs @@ -96,6 +96,7 @@ fn parse_create_table_auto_increment() { )]), }, ], + column_options: vec![], }], columns ); @@ -118,6 +119,7 @@ fn parse_create_sqlite_quote() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ColumnDef { name: Ident::with_quote('[', "INDEX").empty_span(), @@ -125,6 +127,7 @@ fn parse_create_sqlite_quote() { collation: None, codec: None, options: vec![], + column_options: vec![], }, ], columns