@@ -10838,8 +10838,19 @@ fn parse_is_boolean() {
1083810838 verified_stmt("SELECT f FROM foo WHERE field IS UNKNOWN");
1083910839 verified_stmt("SELECT f FROM foo WHERE field IS NOT UNKNOWN");
1084010840
10841+ let supported_dialects = all_dialects_where(|d| d.supports_is_json_predicate());
10842+ let unsupported_dialects = all_dialects_where(|d| !d.supports_is_json_predicate());
10843+
1084110844 let sql = "SELECT f from foo where field is 0";
10842- let res = parse_sql_statements(sql);
10845+ let res = supported_dialects.parse_sql_statements(sql);
10846+ assert_eq!(
10847+ ParserError::ParserError(
10848+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: 0"
10849+ .to_string()
10850+ ),
10851+ res.unwrap_err()
10852+ );
10853+ let res = unsupported_dialects.parse_sql_statements(sql);
1084310854 assert_eq!(
1084410855 ParserError::ParserError(
1084510856 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: 0"
@@ -10849,7 +10860,15 @@ fn parse_is_boolean() {
1084910860 );
1085010861
1085110862 let sql = "SELECT s, s IS XYZ NORMALIZED FROM foo";
10852- let res = parse_sql_statements(sql);
10863+ let res = supported_dialects.parse_sql_statements(sql);
10864+ assert_eq!(
10865+ ParserError::ParserError(
10866+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: XYZ"
10867+ .to_string()
10868+ ),
10869+ res.unwrap_err()
10870+ );
10871+ let res = unsupported_dialects.parse_sql_statements(sql);
1085310872 assert_eq!(
1085410873 ParserError::ParserError(
1085510874 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: XYZ"
@@ -10859,7 +10878,15 @@ fn parse_is_boolean() {
1085910878 );
1086010879
1086110880 let sql = "SELECT s, s IS NFKC FROM foo";
10862- let res = parse_sql_statements(sql);
10881+ let res = supported_dialects.parse_sql_statements(sql);
10882+ assert_eq!(
10883+ ParserError::ParserError(
10884+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: FROM"
10885+ .to_string()
10886+ ),
10887+ res.unwrap_err()
10888+ );
10889+ let res = unsupported_dialects.parse_sql_statements(sql);
1086310890 assert_eq!(
1086410891 ParserError::ParserError(
1086510892 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: FROM"
@@ -10869,7 +10896,15 @@ fn parse_is_boolean() {
1086910896 );
1087010897
1087110898 let sql = "SELECT s, s IS TRIM(' NFKC ') FROM foo";
10872- let res = parse_sql_statements(sql);
10899+ let res = supported_dialects.parse_sql_statements(sql);
10900+ assert_eq!(
10901+ ParserError::ParserError(
10902+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: TRIM"
10903+ .to_string()
10904+ ),
10905+ res.unwrap_err()
10906+ );
10907+ let res = unsupported_dialects.parse_sql_statements(sql);
1087310908 assert_eq!(
1087410909 ParserError::ParserError(
1087510910 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: TRIM"
@@ -10879,6 +10914,221 @@ fn parse_is_boolean() {
1087910914 );
1088010915}
1088110916
10917+ #[test]
10918+ fn parse_is_json_predicate() {
10919+ use self::Expr::*;
10920+
10921+ let supported_dialects = all_dialects_where(|d| d.supports_is_json_predicate());
10922+
10923+ let sql = "a IS JSON";
10924+ assert_eq!(
10925+ IsJson {
10926+ expr: Box::new(Identifier(Ident::new("a"))),
10927+ kind: None,
10928+ unique_keys: None,
10929+ negated: false,
10930+ },
10931+ supported_dialects.verified_expr(sql)
10932+ );
10933+
10934+ let sql = "a IS NOT JSON";
10935+ assert_eq!(
10936+ IsJson {
10937+ expr: Box::new(Identifier(Ident::new("a"))),
10938+ kind: None,
10939+ unique_keys: None,
10940+ negated: true,
10941+ },
10942+ supported_dialects.verified_expr(sql)
10943+ );
10944+
10945+ let sql = "a IS JSON VALUE";
10946+ assert_eq!(
10947+ IsJson {
10948+ expr: Box::new(Identifier(Ident::new("a"))),
10949+ kind: Some(JsonPredicateType::Value),
10950+ unique_keys: None,
10951+ negated: false,
10952+ },
10953+ supported_dialects.verified_expr(sql)
10954+ );
10955+
10956+ let sql = "a IS JSON SCALAR";
10957+ assert_eq!(
10958+ IsJson {
10959+ expr: Box::new(Identifier(Ident::new("a"))),
10960+ kind: Some(JsonPredicateType::Scalar),
10961+ unique_keys: None,
10962+ negated: false,
10963+ },
10964+ supported_dialects.verified_expr(sql)
10965+ );
10966+
10967+ let sql = "a IS JSON ARRAY";
10968+ assert_eq!(
10969+ IsJson {
10970+ expr: Box::new(Identifier(Ident::new("a"))),
10971+ kind: Some(JsonPredicateType::Array),
10972+ unique_keys: None,
10973+ negated: false,
10974+ },
10975+ supported_dialects.verified_expr(sql)
10976+ );
10977+
10978+ let sql = "a IS JSON OBJECT";
10979+ assert_eq!(
10980+ IsJson {
10981+ expr: Box::new(Identifier(Ident::new("a"))),
10982+ kind: Some(JsonPredicateType::Object),
10983+ unique_keys: None,
10984+ negated: false,
10985+ },
10986+ supported_dialects.verified_expr(sql)
10987+ );
10988+
10989+ let sql = "a IS JSON WITH UNIQUE KEYS";
10990+ assert_eq!(
10991+ IsJson {
10992+ expr: Box::new(Identifier(Ident::new("a"))),
10993+ kind: None,
10994+ unique_keys: Some(JsonKeyUniqueness::WithUniqueKeys),
10995+ negated: false,
10996+ },
10997+ supported_dialects.verified_expr(sql)
10998+ );
10999+
11000+ let sql = "a IS JSON WITHOUT UNIQUE KEYS";
11001+ assert_eq!(
11002+ IsJson {
11003+ expr: Box::new(Identifier(Ident::new("a"))),
11004+ kind: None,
11005+ unique_keys: Some(JsonKeyUniqueness::WithoutUniqueKeys),
11006+ negated: false,
11007+ },
11008+ supported_dialects.verified_expr(sql)
11009+ );
11010+
11011+ let sql = "a IS NOT JSON OBJECT WITHOUT UNIQUE KEYS";
11012+ assert_eq!(
11013+ IsJson {
11014+ expr: Box::new(Identifier(Ident::new("a"))),
11015+ kind: Some(JsonPredicateType::Object),
11016+ unique_keys: Some(JsonKeyUniqueness::WithoutUniqueKeys),
11017+ negated: true,
11018+ },
11019+ supported_dialects.verified_expr(sql)
11020+ );
11021+
11022+ supported_dialects.expr_parses_to("a IS JSON WITH UNIQUE", "a IS JSON WITH UNIQUE KEYS");
11023+ supported_dialects.expr_parses_to("a IS JSON WITHOUT UNIQUE", "a IS JSON WITHOUT UNIQUE KEYS");
11024+
11025+ assert_matches!(
11026+ supported_dialects.verified_expr("NOT a IS JSON"),
11027+ Expr::UnaryOp {
11028+ op: UnaryOperator::Not,
11029+ expr
11030+ } if matches!(&*expr, Expr::IsJson { .. })
11031+ );
11032+ }
11033+
11034+ #[test]
11035+ fn parse_is_json_predicate_unsupported_dialects() {
11036+ let unsupported_dialects = all_dialects_where(|d| !d.supports_is_json_predicate());
11037+ assert!(!unsupported_dialects.dialects.is_empty());
11038+
11039+ for sql in ["SELECT a IS JSON FROM t", "SELECT a IS NOT JSON FROM t"] {
11040+ let err = unsupported_dialects.parse_sql_statements(sql).unwrap_err();
11041+ let ParserError::ParserError(msg) = err else {
11042+ panic!("Expected ParserError::ParserError for `{sql}`, got: {err:?}");
11043+ };
11044+ assert!(
11045+ msg.contains("[NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS"),
11046+ "Unexpected error hint for unsupported dialects in `{sql}`: {msg}"
11047+ );
11048+ assert!(
11049+ !msg.contains("[NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT]"),
11050+ "Unsupported dialects should not advertise JSON IS-predicate syntax in `{sql}`: {msg}"
11051+ );
11052+ assert!(
11053+ msg.contains("found: JSON"),
11054+ "Expected parser to fail at JSON token for unsupported dialects in `{sql}`: {msg}"
11055+ );
11056+ }
11057+ }
11058+
11059+ #[test]
11060+ fn parse_is_json_predicate_negative() {
11061+ let supported_dialects = all_dialects_where(|d| d.supports_is_json_predicate());
11062+
11063+ let cases = [
11064+ (
11065+ "SELECT * FROM t WHERE a IS JSON WITH FROM",
11066+ &["Expected: UNIQUE", "found: FROM"][..],
11067+ ),
11068+ (
11069+ "SELECT * FROM t WHERE a IS JSON WITH KEYS",
11070+ &["Expected: UNIQUE", "found: KEYS"][..],
11071+ ),
11072+ (
11073+ "SELECT * FROM t WHERE a IS JSON WITHOUT FROM",
11074+ &["Expected: UNIQUE", "found: FROM"][..],
11075+ ),
11076+ (
11077+ "SELECT * FROM t WHERE a IS JSON WITHOUT KEYS",
11078+ &["Expected: UNIQUE", "found: KEYS"][..],
11079+ ),
11080+ (
11081+ "SELECT * FROM t WHERE a IS NOT JSON WITH FROM",
11082+ &["Expected: UNIQUE", "found: FROM"][..],
11083+ ),
11084+ (
11085+ "SELECT * FROM t WHERE a IS JSON VALUE ARRAY",
11086+ &["Expected: end of statement", "found: ARRAY"][..],
11087+ ),
11088+ (
11089+ "SELECT * FROM t WHERE a IS JSON OBJECT VALUE",
11090+ &["Expected: end of statement", "found: VALUE"][..],
11091+ ),
11092+ (
11093+ "SELECT * FROM t WHERE a IS JSON WITH UNIQUE EXTRA",
11094+ &["Expected: end of statement", "found: EXTRA"][..],
11095+ ),
11096+ (
11097+ "SELECT * FROM t WHERE a IS JSON WITH UNIQUE KEYS EXTRA",
11098+ &["Expected: end of statement", "found: EXTRA"][..],
11099+ ),
11100+ (
11101+ "SELECT * FROM t WHERE a IS JSON WITHOUT UNIQUE EXTRA",
11102+ &["Expected: end of statement", "found: EXTRA"][..],
11103+ ),
11104+ (
11105+ "SELECT * FROM t WHERE a IS JSON WITHOUT UNIQUE KEYS EXTRA",
11106+ &["Expected: end of statement", "found: EXTRA"][..],
11107+ ),
11108+ (
11109+ "SELECT * FROM t WHERE a IS JSON WITH UNIQUE KEYS WITH UNIQUE KEYS",
11110+ &["Expected: end of statement", "found: WITH"][..],
11111+ ),
11112+ (
11113+ "SELECT * FROM t WHERE a IS JSON WITHOUT UNIQUE KEYS WITHOUT UNIQUE KEYS",
11114+ &["Expected: end of statement", "found: WITHOUT"][..],
11115+ ),
11116+ ];
11117+
11118+ for (sql, expected_fragments) in cases {
11119+ let err = supported_dialects.parse_sql_statements(sql).unwrap_err();
11120+ let ParserError::ParserError(msg) = err else {
11121+ panic!("Expected ParserError::ParserError for `{sql}`, got: {err:?}");
11122+ };
11123+ for fragment in expected_fragments {
11124+ assert!(
11125+ msg.contains(fragment),
11126+ "Expected parser diagnostic for `{sql}` to contain `{fragment}`, got: {msg}"
11127+ );
11128+ }
11129+ }
11130+ }
11131+
1088211132#[test]
1088311133fn parse_discard() {
1088411134 let sql = "DISCARD ALL";
0 commit comments