@@ -15988,3 +15988,135 @@ fn parse_create_procedure_with_parameter_modes() {
1598815988 _ => unreachable!(),
1598915989 }
1599015990}
15991+
15992+ #[test]
15993+ fn parse_not_null_unsupported() {
15994+ // Only DuckDB and SQLite support `x NOT NULL` as an expression
15995+ // All other dialects fail to parse.
15996+ let sql = r#"WITH t AS (SELECT NULL AS x) SELECT x NOT NULL FROM t"#;
15997+ let dialects = all_dialects_except(|d| d.supports_not_null());
15998+ let res = dialects.parse_sql_statements(sql);
15999+ assert_eq!(
16000+ ParserError::ParserError("Expected: end of statement, found: NULL".to_string()),
16001+ res.unwrap_err()
16002+ );
16003+ }
16004+
16005+ #[test]
16006+ fn parse_not_null_supported() {
16007+ // DuckDB and SQLite support `x NOT NULL` as an expression
16008+ let sql = r#"WITH t AS (SELECT NULL AS x) SELECT x NOT NULL FROM t"#;
16009+ let dialects = all_dialects_where(|d| d.supports_not_null());
16010+ let stmt = dialects.one_statement_parses_to(sql, sql);
16011+ match stmt {
16012+ Statement::Query(qry) => match *qry.body {
16013+ SetExpr::Select(select) => {
16014+ assert_eq!(select.projection.len(), 1);
16015+ match select.projection.first().unwrap() {
16016+ UnnamedExpr(expr) => {
16017+ let fake_span = Span {
16018+ start: Location { line: 0, column: 0 },
16019+ end: Location { line: 0, column: 0 },
16020+ };
16021+ assert_eq!(
16022+ *expr,
16023+ Expr::NotNull {
16024+ expr: Box::new(Identifier(Ident {
16025+ value: "x".to_string(),
16026+ quote_style: None,
16027+ span: fake_span,
16028+ })),
16029+ one_word: false,
16030+ },
16031+ );
16032+ }
16033+ _ => unreachable!(),
16034+ }
16035+ }
16036+ _ => unreachable!(),
16037+ },
16038+ _ => unreachable!(),
16039+ }
16040+ }
16041+
16042+ #[test]
16043+ fn parse_notnull_unsupported() {
16044+ // Only Postgres, DuckDB, and SQLite support `x NOTNULL` as an expression
16045+ // All other dialects consider `x NOTNULL` like `x AS NOTNULL` and thus
16046+ // consider `NOTNULL` an alias for x.
16047+ let sql = r#"WITH t AS (SELECT NULL AS x) SELECT x NOTNULL FROM t"#;
16048+ let canonical = r#"WITH t AS (SELECT NULL AS x) SELECT x AS NOTNULL FROM t"#;
16049+ let dialects = all_dialects_except(|d| d.supports_notnull());
16050+ let stmt = dialects.one_statement_parses_to(sql, canonical);
16051+ match stmt {
16052+ Statement::Query(qry) => match *qry.body {
16053+ SetExpr::Select(select) => {
16054+ assert_eq!(select.projection.len(), 1);
16055+ match select.projection.first().unwrap() {
16056+ SelectItem::ExprWithAlias { expr, alias } => {
16057+ let fake_span = Span {
16058+ start: Location { line: 0, column: 0 },
16059+ end: Location { line: 0, column: 0 },
16060+ };
16061+ assert_eq!(
16062+ *expr,
16063+ Identifier(Ident {
16064+ value: "x".to_string(),
16065+ quote_style: None,
16066+ span: fake_span,
16067+ })
16068+ );
16069+ assert_eq!(
16070+ *alias,
16071+ Ident {
16072+ value: "NOTNULL".to_string(),
16073+ quote_style: None,
16074+ span: fake_span,
16075+ }
16076+ );
16077+ }
16078+ _ => unreachable!(),
16079+ }
16080+ }
16081+ _ => unreachable!(),
16082+ },
16083+ _ => unreachable!(),
16084+ }
16085+ }
16086+
16087+ #[test]
16088+ fn parse_notnull_supported() {
16089+ // DuckDB and SQLite support `x NOT NULL` as an expression
16090+ let sql = r#"WITH t AS (SELECT NULL AS x) SELECT x NOTNULL FROM t"#;
16091+ let dialects = all_dialects_where(|d| d.supports_notnull());
16092+ let stmt = dialects.one_statement_parses_to(sql, "");
16093+ match stmt {
16094+ Statement::Query(qry) => match *qry.body {
16095+ SetExpr::Select(select) => {
16096+ assert_eq!(select.projection.len(), 1);
16097+ match select.projection.first().unwrap() {
16098+ UnnamedExpr(expr) => {
16099+ let fake_span = Span {
16100+ start: Location { line: 0, column: 0 },
16101+ end: Location { line: 0, column: 0 },
16102+ };
16103+ assert_eq!(
16104+ *expr,
16105+ Expr::NotNull {
16106+ expr: Box::new(Identifier(Ident {
16107+ value: "x".to_string(),
16108+ quote_style: None,
16109+ span: fake_span,
16110+ })),
16111+ one_word: true,
16112+ },
16113+ );
16114+ }
16115+ _ => unreachable!(),
16116+ }
16117+ }
16118+ _ => unreachable!(),
16119+ },
16120+ _ => unreachable!(),
16121+ }
16122+ }
0 commit comments