@@ -10747,8 +10747,19 @@ fn parse_is_boolean() {
1074710747 verified_stmt("SELECT f FROM foo WHERE field IS UNKNOWN");
1074810748 verified_stmt("SELECT f FROM foo WHERE field IS NOT UNKNOWN");
1074910749
10750+ let supported_dialects = all_dialects_where(|d| d.supports_is_json_predicate());
10751+ let unsupported_dialects = all_dialects_where(|d| !d.supports_is_json_predicate());
10752+
1075010753 let sql = "SELECT f from foo where field is 0";
10751- let res = parse_sql_statements(sql);
10754+ let res = supported_dialects.parse_sql_statements(sql);
10755+ assert_eq!(
10756+ ParserError::ParserError(
10757+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: 0"
10758+ .to_string()
10759+ ),
10760+ res.unwrap_err()
10761+ );
10762+ let res = unsupported_dialects.parse_sql_statements(sql);
1075210763 assert_eq!(
1075310764 ParserError::ParserError(
1075410765 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: 0"
@@ -10758,7 +10769,15 @@ fn parse_is_boolean() {
1075810769 );
1075910770
1076010771 let sql = "SELECT s, s IS XYZ NORMALIZED FROM foo";
10761- let res = parse_sql_statements(sql);
10772+ let res = supported_dialects.parse_sql_statements(sql);
10773+ assert_eq!(
10774+ ParserError::ParserError(
10775+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: XYZ"
10776+ .to_string()
10777+ ),
10778+ res.unwrap_err()
10779+ );
10780+ let res = unsupported_dialects.parse_sql_statements(sql);
1076210781 assert_eq!(
1076310782 ParserError::ParserError(
1076410783 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: XYZ"
@@ -10768,7 +10787,15 @@ fn parse_is_boolean() {
1076810787 );
1076910788
1077010789 let sql = "SELECT s, s IS NFKC FROM foo";
10771- let res = parse_sql_statements(sql);
10790+ let res = supported_dialects.parse_sql_statements(sql);
10791+ assert_eq!(
10792+ ParserError::ParserError(
10793+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: FROM"
10794+ .to_string()
10795+ ),
10796+ res.unwrap_err()
10797+ );
10798+ let res = unsupported_dialects.parse_sql_statements(sql);
1077210799 assert_eq!(
1077310800 ParserError::ParserError(
1077410801 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: FROM"
@@ -10778,7 +10805,15 @@ fn parse_is_boolean() {
1077810805 );
1077910806
1078010807 let sql = "SELECT s, s IS TRIM(' NFKC ') FROM foo";
10781- let res = parse_sql_statements(sql);
10808+ let res = supported_dialects.parse_sql_statements(sql);
10809+ assert_eq!(
10810+ ParserError::ParserError(
10811+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: TRIM"
10812+ .to_string()
10813+ ),
10814+ res.unwrap_err()
10815+ );
10816+ let res = unsupported_dialects.parse_sql_statements(sql);
1078210817 assert_eq!(
1078310818 ParserError::ParserError(
1078410819 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: TRIM"
@@ -10788,6 +10823,221 @@ fn parse_is_boolean() {
1078810823 );
1078910824}
1079010825
10826+ #[test]
10827+ fn parse_is_json_predicate() {
10828+ use self::Expr::*;
10829+
10830+ let supported_dialects = all_dialects_where(|d| d.supports_is_json_predicate());
10831+
10832+ let sql = "a IS JSON";
10833+ assert_eq!(
10834+ IsJson {
10835+ expr: Box::new(Identifier(Ident::new("a"))),
10836+ kind: None,
10837+ unique_keys: None,
10838+ negated: false,
10839+ },
10840+ supported_dialects.verified_expr(sql)
10841+ );
10842+
10843+ let sql = "a IS NOT JSON";
10844+ assert_eq!(
10845+ IsJson {
10846+ expr: Box::new(Identifier(Ident::new("a"))),
10847+ kind: None,
10848+ unique_keys: None,
10849+ negated: true,
10850+ },
10851+ supported_dialects.verified_expr(sql)
10852+ );
10853+
10854+ let sql = "a IS JSON VALUE";
10855+ assert_eq!(
10856+ IsJson {
10857+ expr: Box::new(Identifier(Ident::new("a"))),
10858+ kind: Some(JsonPredicateType::Value),
10859+ unique_keys: None,
10860+ negated: false,
10861+ },
10862+ supported_dialects.verified_expr(sql)
10863+ );
10864+
10865+ let sql = "a IS JSON SCALAR";
10866+ assert_eq!(
10867+ IsJson {
10868+ expr: Box::new(Identifier(Ident::new("a"))),
10869+ kind: Some(JsonPredicateType::Scalar),
10870+ unique_keys: None,
10871+ negated: false,
10872+ },
10873+ supported_dialects.verified_expr(sql)
10874+ );
10875+
10876+ let sql = "a IS JSON ARRAY";
10877+ assert_eq!(
10878+ IsJson {
10879+ expr: Box::new(Identifier(Ident::new("a"))),
10880+ kind: Some(JsonPredicateType::Array),
10881+ unique_keys: None,
10882+ negated: false,
10883+ },
10884+ supported_dialects.verified_expr(sql)
10885+ );
10886+
10887+ let sql = "a IS JSON OBJECT";
10888+ assert_eq!(
10889+ IsJson {
10890+ expr: Box::new(Identifier(Ident::new("a"))),
10891+ kind: Some(JsonPredicateType::Object),
10892+ unique_keys: None,
10893+ negated: false,
10894+ },
10895+ supported_dialects.verified_expr(sql)
10896+ );
10897+
10898+ let sql = "a IS JSON WITH UNIQUE KEYS";
10899+ assert_eq!(
10900+ IsJson {
10901+ expr: Box::new(Identifier(Ident::new("a"))),
10902+ kind: None,
10903+ unique_keys: Some(JsonKeyUniqueness::WithUniqueKeys),
10904+ negated: false,
10905+ },
10906+ supported_dialects.verified_expr(sql)
10907+ );
10908+
10909+ let sql = "a IS JSON WITHOUT UNIQUE KEYS";
10910+ assert_eq!(
10911+ IsJson {
10912+ expr: Box::new(Identifier(Ident::new("a"))),
10913+ kind: None,
10914+ unique_keys: Some(JsonKeyUniqueness::WithoutUniqueKeys),
10915+ negated: false,
10916+ },
10917+ supported_dialects.verified_expr(sql)
10918+ );
10919+
10920+ let sql = "a IS NOT JSON OBJECT WITHOUT UNIQUE KEYS";
10921+ assert_eq!(
10922+ IsJson {
10923+ expr: Box::new(Identifier(Ident::new("a"))),
10924+ kind: Some(JsonPredicateType::Object),
10925+ unique_keys: Some(JsonKeyUniqueness::WithoutUniqueKeys),
10926+ negated: true,
10927+ },
10928+ supported_dialects.verified_expr(sql)
10929+ );
10930+
10931+ supported_dialects.expr_parses_to("a IS JSON WITH UNIQUE", "a IS JSON WITH UNIQUE KEYS");
10932+ supported_dialects.expr_parses_to("a IS JSON WITHOUT UNIQUE", "a IS JSON WITHOUT UNIQUE KEYS");
10933+
10934+ assert_matches!(
10935+ supported_dialects.verified_expr("NOT a IS JSON"),
10936+ Expr::UnaryOp {
10937+ op: UnaryOperator::Not,
10938+ expr
10939+ } if matches!(&*expr, Expr::IsJson { .. })
10940+ );
10941+ }
10942+
10943+ #[test]
10944+ fn parse_is_json_predicate_unsupported_dialects() {
10945+ let unsupported_dialects = all_dialects_where(|d| !d.supports_is_json_predicate());
10946+ assert!(!unsupported_dialects.dialects.is_empty());
10947+
10948+ for sql in ["SELECT a IS JSON FROM t", "SELECT a IS NOT JSON FROM t"] {
10949+ let err = unsupported_dialects.parse_sql_statements(sql).unwrap_err();
10950+ let ParserError::ParserError(msg) = err else {
10951+ panic!("Expected ParserError::ParserError for `{sql}`, got: {err:?}");
10952+ };
10953+ assert!(
10954+ msg.contains("[NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS"),
10955+ "Unexpected error hint for unsupported dialects in `{sql}`: {msg}"
10956+ );
10957+ assert!(
10958+ !msg.contains("[NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT]"),
10959+ "Unsupported dialects should not advertise JSON IS-predicate syntax in `{sql}`: {msg}"
10960+ );
10961+ assert!(
10962+ msg.contains("found: JSON"),
10963+ "Expected parser to fail at JSON token for unsupported dialects in `{sql}`: {msg}"
10964+ );
10965+ }
10966+ }
10967+
10968+ #[test]
10969+ fn parse_is_json_predicate_negative() {
10970+ let supported_dialects = all_dialects_where(|d| d.supports_is_json_predicate());
10971+
10972+ let cases = [
10973+ (
10974+ "SELECT * FROM t WHERE a IS JSON WITH FROM",
10975+ &["Expected: UNIQUE", "found: FROM"][..],
10976+ ),
10977+ (
10978+ "SELECT * FROM t WHERE a IS JSON WITH KEYS",
10979+ &["Expected: UNIQUE", "found: KEYS"][..],
10980+ ),
10981+ (
10982+ "SELECT * FROM t WHERE a IS JSON WITHOUT FROM",
10983+ &["Expected: UNIQUE", "found: FROM"][..],
10984+ ),
10985+ (
10986+ "SELECT * FROM t WHERE a IS JSON WITHOUT KEYS",
10987+ &["Expected: UNIQUE", "found: KEYS"][..],
10988+ ),
10989+ (
10990+ "SELECT * FROM t WHERE a IS NOT JSON WITH FROM",
10991+ &["Expected: UNIQUE", "found: FROM"][..],
10992+ ),
10993+ (
10994+ "SELECT * FROM t WHERE a IS JSON VALUE ARRAY",
10995+ &["Expected: end of statement", "found: ARRAY"][..],
10996+ ),
10997+ (
10998+ "SELECT * FROM t WHERE a IS JSON OBJECT VALUE",
10999+ &["Expected: end of statement", "found: VALUE"][..],
11000+ ),
11001+ (
11002+ "SELECT * FROM t WHERE a IS JSON WITH UNIQUE EXTRA",
11003+ &["Expected: end of statement", "found: EXTRA"][..],
11004+ ),
11005+ (
11006+ "SELECT * FROM t WHERE a IS JSON WITH UNIQUE KEYS EXTRA",
11007+ &["Expected: end of statement", "found: EXTRA"][..],
11008+ ),
11009+ (
11010+ "SELECT * FROM t WHERE a IS JSON WITHOUT UNIQUE EXTRA",
11011+ &["Expected: end of statement", "found: EXTRA"][..],
11012+ ),
11013+ (
11014+ "SELECT * FROM t WHERE a IS JSON WITHOUT UNIQUE KEYS EXTRA",
11015+ &["Expected: end of statement", "found: EXTRA"][..],
11016+ ),
11017+ (
11018+ "SELECT * FROM t WHERE a IS JSON WITH UNIQUE KEYS WITH UNIQUE KEYS",
11019+ &["Expected: end of statement", "found: WITH"][..],
11020+ ),
11021+ (
11022+ "SELECT * FROM t WHERE a IS JSON WITHOUT UNIQUE KEYS WITHOUT UNIQUE KEYS",
11023+ &["Expected: end of statement", "found: WITHOUT"][..],
11024+ ),
11025+ ];
11026+
11027+ for (sql, expected_fragments) in cases {
11028+ let err = supported_dialects.parse_sql_statements(sql).unwrap_err();
11029+ let ParserError::ParserError(msg) = err else {
11030+ panic!("Expected ParserError::ParserError for `{sql}`, got: {err:?}");
11031+ };
11032+ for fragment in expected_fragments {
11033+ assert!(
11034+ msg.contains(fragment),
11035+ "Expected parser diagnostic for `{sql}` to contain `{fragment}`, got: {msg}"
11036+ );
11037+ }
11038+ }
11039+ }
11040+
1079111041#[test]
1079211042fn parse_discard() {
1079311043 let sql = "DISCARD ALL";
0 commit comments