Add support for INVISIBLE columns in MySQL (#2033)

This commit is contained in:
Marcelo Altmann 2025-09-23 08:07:50 -03:00 committed by GitHub
parent 3c61db5dc0
commit a15c70dff9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 68 additions and 1 deletions

View file

@ -1911,6 +1911,13 @@ pub enum ColumnOption {
/// ``` /// ```
/// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/creating-spatial-indexes.html /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/creating-spatial-indexes.html
Srid(Box<Expr>), Srid(Box<Expr>),
/// MySQL specific: Column is invisible via SELECT *
/// Syntax:
/// ```sql
/// CREATE TABLE t (foo INT, bar INT INVISIBLE);
/// ```
/// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/invisible-columns.html
Invisible,
} }
impl fmt::Display for ColumnOption { impl fmt::Display for ColumnOption {
@ -2029,6 +2036,9 @@ impl fmt::Display for ColumnOption {
Srid(srid) => { Srid(srid) => {
write!(f, "SRID {srid}") write!(f, "SRID {srid}")
} }
Invisible => {
write!(f, "INVISIBLE")
}
} }
} }
} }

View file

@ -918,6 +918,7 @@ impl Spanned for ColumnOption {
ColumnOption::Policy(..) => Span::empty(), ColumnOption::Policy(..) => Span::empty(),
ColumnOption::Tags(..) => Span::empty(), ColumnOption::Tags(..) => Span::empty(),
ColumnOption::Srid(..) => Span::empty(), ColumnOption::Srid(..) => Span::empty(),
ColumnOption::Invisible => Span::empty(),
} }
} }
} }

View file

@ -499,6 +499,7 @@ define_keywords!(
INTERSECTION, INTERSECTION,
INTERVAL, INTERVAL,
INTO, INTO,
INVISIBLE,
INVOKER, INVOKER,
IO, IO,
IS, IS,

View file

@ -8144,6 +8144,8 @@ impl<'a> Parser<'a> {
Keyword::REPLACE, Keyword::REPLACE,
])?, ])?,
))) )))
} else if self.parse_keyword(Keyword::INVISIBLE) {
Ok(Some(ColumnOption::Invisible))
} else { } else {
Ok(None) Ok(None)
} }

View file

@ -17138,7 +17138,7 @@ fn test_parse_semantic_view_table_factor() {
} }
let ast_sql = r#"SELECT * FROM SEMANTIC_VIEW( let ast_sql = r#"SELECT * FROM SEMANTIC_VIEW(
my_model my_model
DIMENSIONS DATE_PART('year', date_col), region_name DIMENSIONS DATE_PART('year', date_col), region_name
METRICS orders.revenue, orders.count METRICS orders.revenue, orders.count
WHERE active = true WHERE active = true
@ -17193,3 +17193,56 @@ fn parse_adjacent_string_literal_concatenation() {
let sql = "SELECT * FROM t WHERE col = 'Hello' \n ' ' \t 'World!'"; let sql = "SELECT * FROM t WHERE col = 'Hello' \n ' ' \t 'World!'";
dialects.one_statement_parses_to(sql, r"SELECT * FROM t WHERE col = 'Hello World!'"); dialects.one_statement_parses_to(sql, r"SELECT * FROM t WHERE col = 'Hello World!'");
} }
#[test]
fn parse_invisible_column() {
let sql = r#"CREATE TABLE t (foo INT, bar INT INVISIBLE)"#;
let stmt = verified_stmt(sql);
match stmt {
Statement::CreateTable(CreateTable { columns, .. }) => {
assert_eq!(
columns,
vec![
ColumnDef {
name: "foo".into(),
data_type: DataType::Int(None),
options: vec![]
},
ColumnDef {
name: "bar".into(),
data_type: DataType::Int(None),
options: vec![ColumnOptionDef {
name: None,
option: ColumnOption::Invisible
}]
}
]
);
}
_ => panic!("Unexpected statement {stmt}"),
}
let sql = r#"ALTER TABLE t ADD COLUMN bar INT INVISIBLE"#;
let stmt = verified_stmt(sql);
match stmt {
Statement::AlterTable { operations, .. } => {
assert_eq!(
operations,
vec![AlterTableOperation::AddColumn {
column_keyword: true,
if_not_exists: false,
column_def: ColumnDef {
name: "bar".into(),
data_type: DataType::Int(None),
options: vec![ColumnOptionDef {
name: None,
option: ColumnOption::Invisible
}]
},
column_position: None
}]
);
}
_ => panic!("Unexpected statement {stmt}"),
}
}