From 5e5604fddcbdf7ddddd32fc2a589e2284ef36696 Mon Sep 17 00:00:00 2001 From: Riccardo Azzolini Date: Tue, 24 May 2022 10:07:11 +0200 Subject: [PATCH] Distinguish between tables and nullary functions in FROM --- src/ast/query.rs | 8 ++++++-- src/parser.rs | 4 ++-- src/test_utils.rs | 2 +- tests/sqlparser_bigquery.rs | 2 +- tests/sqlparser_common.rs | 36 ++++++++++++++++++++--------------- tests/sqlparser_mysql.rs | 6 +++--- tests/sqlparser_postgres.rs | 4 ++-- tests/sqlparser_redshift.rs | 4 ++-- tests/sqpparser_clickhouse.rs | 2 +- 9 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/ast/query.rs b/src/ast/query.rs index 472b9e6ba..07295f44f 100644 --- a/src/ast/query.rs +++ b/src/ast/query.rs @@ -337,7 +337,11 @@ pub enum TableFactor { /// Arguments of a table-valued function, as supported by Postgres /// and MSSQL. Note that deprecated MSSQL `FROM foo (NOLOCK)` syntax /// will also be parsed as `args`. - args: Vec, + /// + /// This field's value is `Some(v)`, where `v` is a (possibly empty) + /// vector of arguments, in the case of a table-valued function call, + /// whereas it's `None` in the case of a regular table name. + args: Option>, /// MSSQL-specific `WITH (...)` hints such as NOLOCK. with_hints: Vec, }, @@ -370,7 +374,7 @@ impl fmt::Display for TableFactor { with_hints, } => { write!(f, "{}", name)?; - if !args.is_empty() { + if let Some(args) = args { write!(f, "({})", display_comma_separated(args))?; } if let Some(alias) = alias { diff --git a/src/parser.rs b/src/parser.rs index 6a3c9c442..0348d533f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3620,9 +3620,9 @@ impl<'a> Parser<'a> { let name = self.parse_object_name()?; // Postgres, MSSQL: table-valued functions: let args = if self.consume_token(&Token::LParen) { - self.parse_optional_args()? + Some(self.parse_optional_args()?) } else { - vec![] + None }; let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?; // MSSQL-specific table hints: diff --git a/src/test_utils.rs b/src/test_utils.rs index 1a432e47a..deb3e2580 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -177,7 +177,7 @@ pub fn table(name: impl Into) -> TableFactor { TableFactor::Table { name: ObjectName(vec![Ident::new(name.into())]), alias: None, - args: vec![], + args: None, with_hints: vec![], } } diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs index 380530199..2b49abf6f 100644 --- a/tests/sqlparser_bigquery.rs +++ b/tests/sqlparser_bigquery.rs @@ -29,7 +29,7 @@ fn parse_table_identifiers() { relation: TableFactor::Table { name: ObjectName(expected), alias: None, - args: vec![], + args: None, with_hints: vec![], }, joins: vec![] diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 46d824175..715c30bda 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -200,7 +200,7 @@ fn parse_update_with_table_alias() { name: Ident::new("u"), columns: vec![] }), - args: vec![], + args: None, with_hints: vec![], }, joins: vec![] @@ -2793,7 +2793,7 @@ fn parse_delimited_identifiers() { } => { assert_eq!(vec![Ident::with_quote('"', "a table")], name.0); assert_eq!(Ident::with_quote('"', "alias"), alias.unwrap().name); - assert!(args.is_empty()); + assert!(args.is_none()); assert!(with_hints.is_empty()); } _ => panic!("Expecting TableFactor::Table"), @@ -2912,6 +2912,12 @@ fn parse_from_advanced() { let _select = verified_only_select(sql); } +#[test] +fn parse_nullary_table_valued_function() { + let sql = "SELECT * FROM fn()"; + let _select = verified_only_select(sql); +} + #[test] fn parse_implicit_join() { let sql = "SELECT * FROM t1, t2"; @@ -2922,7 +2928,7 @@ fn parse_implicit_join() { relation: TableFactor::Table { name: ObjectName(vec!["t1".into()]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, joins: vec![], @@ -2931,7 +2937,7 @@ fn parse_implicit_join() { relation: TableFactor::Table { name: ObjectName(vec!["t2".into()]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, joins: vec![], @@ -2948,14 +2954,14 @@ fn parse_implicit_join() { relation: TableFactor::Table { name: ObjectName(vec!["t1a".into()]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, joins: vec![Join { relation: TableFactor::Table { name: ObjectName(vec!["t1b".into()]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, join_operator: JoinOperator::Inner(JoinConstraint::Natural), @@ -2965,14 +2971,14 @@ fn parse_implicit_join() { relation: TableFactor::Table { name: ObjectName(vec!["t2a".into()]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, joins: vec![Join { relation: TableFactor::Table { name: ObjectName(vec!["t2b".into()]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, join_operator: JoinOperator::Inner(JoinConstraint::Natural), @@ -2992,7 +2998,7 @@ fn parse_cross_join() { relation: TableFactor::Table { name: ObjectName(vec![Ident::new("t2")]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, join_operator: JoinOperator::CrossJoin @@ -3012,7 +3018,7 @@ fn parse_joins_on() { relation: TableFactor::Table { name: ObjectName(vec![Ident::new(relation.into())]), alias, - args: vec![], + args: None, with_hints: vec![], }, join_operator: f(JoinConstraint::On(Expr::BinaryOp { @@ -3065,7 +3071,7 @@ fn parse_joins_using() { relation: TableFactor::Table { name: ObjectName(vec![Ident::new(relation.into())]), alias, - args: vec![], + args: None, with_hints: vec![], }, join_operator: f(JoinConstraint::Using(vec!["c1".into()])), @@ -3110,7 +3116,7 @@ fn parse_natural_join() { relation: TableFactor::Table { name: ObjectName(vec![Ident::new("t2")]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, join_operator: f(JoinConstraint::Natural), @@ -3348,7 +3354,7 @@ fn parse_derived_tables() { relation: TableFactor::Table { name: ObjectName(vec!["t2".into()]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, join_operator: JoinOperator::Inner(JoinConstraint::Natural), @@ -4431,7 +4437,7 @@ fn parse_merge() { name: Ident::new("dest"), columns: vec![] }), - args: vec![], + args: None, with_hints: vec![] } ); @@ -4452,7 +4458,7 @@ fn parse_merge() { relation: TableFactor::Table { name: ObjectName(vec![Ident::new("s"), Ident::new("foo")]), alias: None, - args: vec![], + args: None, with_hints: vec![] }, joins: vec![] diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index ac265875d..9a7117a4a 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -626,7 +626,7 @@ fn parse_update_with_joins() { name: Ident::new("o"), columns: vec![] }), - args: vec![], + args: None, with_hints: vec![], }, joins: vec![Join { @@ -636,7 +636,7 @@ fn parse_update_with_joins() { name: Ident::new("c"), columns: vec![] }), - args: vec![], + args: None, with_hints: vec![], }, join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp { @@ -743,7 +743,7 @@ fn parse_substring_in_select() { quote_style: None }]), alias: None, - args: vec![], + args: None, with_hints: vec![] }, joins: vec![] diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 4fee8083a..547fa308c 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -413,7 +413,7 @@ fn parse_update_set_from() { relation: TableFactor::Table { name: ObjectName(vec![Ident::new("t1")]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, joins: vec![], @@ -439,7 +439,7 @@ fn parse_update_set_from() { relation: TableFactor::Table { name: ObjectName(vec![Ident::new("t1")]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, joins: vec![], diff --git a/tests/sqlparser_redshift.rs b/tests/sqlparser_redshift.rs index ce818a98d..6f77cf335 100644 --- a/tests/sqlparser_redshift.rs +++ b/tests/sqlparser_redshift.rs @@ -43,7 +43,7 @@ fn test_square_brackets_over_db_schema_table_name() { } ]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, joins: vec![], @@ -87,7 +87,7 @@ fn test_double_quotes_over_db_schema_table_name() { } ]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, joins: vec![], diff --git a/tests/sqpparser_clickhouse.rs b/tests/sqpparser_clickhouse.rs index ab8c28f21..72a1a0556 100644 --- a/tests/sqpparser_clickhouse.rs +++ b/tests/sqpparser_clickhouse.rs @@ -58,7 +58,7 @@ fn parse_map_access_expr() { relation: Table { name: ObjectName(vec![Ident::new("foos")]), alias: None, - args: vec![], + args: None, with_hints: vec![], }, joins: vec![]