@@ -10722,8 +10722,19 @@ fn parse_is_boolean() {
1072210722 verified_stmt("SELECT f FROM foo WHERE field IS UNKNOWN");
1072310723 verified_stmt("SELECT f FROM foo WHERE field IS NOT UNKNOWN");
1072410724
10725+ let supported_dialects = all_dialects_where(|d| d.supports_is_json_predicate());
10726+ let unsupported_dialects = all_dialects_where(|d| !d.supports_is_json_predicate());
10727+
1072510728 let sql = "SELECT f from foo where field is 0";
10726- let res = parse_sql_statements(sql);
10729+ let res = supported_dialects.parse_sql_statements(sql);
10730+ assert_eq!(
10731+ ParserError::ParserError(
10732+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: 0"
10733+ .to_string()
10734+ ),
10735+ res.unwrap_err()
10736+ );
10737+ let res = unsupported_dialects.parse_sql_statements(sql);
1072710738 assert_eq!(
1072810739 ParserError::ParserError(
1072910740 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: 0"
@@ -10733,7 +10744,15 @@ fn parse_is_boolean() {
1073310744 );
1073410745
1073510746 let sql = "SELECT s, s IS XYZ NORMALIZED FROM foo";
10736- let res = parse_sql_statements(sql);
10747+ let res = supported_dialects.parse_sql_statements(sql);
10748+ assert_eq!(
10749+ ParserError::ParserError(
10750+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: XYZ"
10751+ .to_string()
10752+ ),
10753+ res.unwrap_err()
10754+ );
10755+ let res = unsupported_dialects.parse_sql_statements(sql);
1073710756 assert_eq!(
1073810757 ParserError::ParserError(
1073910758 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: XYZ"
@@ -10743,7 +10762,15 @@ fn parse_is_boolean() {
1074310762 );
1074410763
1074510764 let sql = "SELECT s, s IS NFKC FROM foo";
10746- let res = parse_sql_statements(sql);
10765+ let res = supported_dialects.parse_sql_statements(sql);
10766+ assert_eq!(
10767+ ParserError::ParserError(
10768+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: FROM"
10769+ .to_string()
10770+ ),
10771+ res.unwrap_err()
10772+ );
10773+ let res = unsupported_dialects.parse_sql_statements(sql);
1074710774 assert_eq!(
1074810775 ParserError::ParserError(
1074910776 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: FROM"
@@ -10753,7 +10780,15 @@ fn parse_is_boolean() {
1075310780 );
1075410781
1075510782 let sql = "SELECT s, s IS TRIM(' NFKC ') FROM foo";
10756- let res = parse_sql_statements(sql);
10783+ let res = supported_dialects.parse_sql_statements(sql);
10784+ assert_eq!(
10785+ ParserError::ParserError(
10786+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: TRIM"
10787+ .to_string()
10788+ ),
10789+ res.unwrap_err()
10790+ );
10791+ let res = unsupported_dialects.parse_sql_statements(sql);
1075710792 assert_eq!(
1075810793 ParserError::ParserError(
1075910794 "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: TRIM"
@@ -10763,6 +10798,221 @@ fn parse_is_boolean() {
1076310798 );
1076410799}
1076510800
10801+ #[test]
10802+ fn parse_is_json_predicate() {
10803+ use self::Expr::*;
10804+
10805+ let supported_dialects = all_dialects_where(|d| d.supports_is_json_predicate());
10806+
10807+ let sql = "a IS JSON";
10808+ assert_eq!(
10809+ IsJson {
10810+ expr: Box::new(Identifier(Ident::new("a"))),
10811+ kind: None,
10812+ unique_keys: None,
10813+ negated: false,
10814+ },
10815+ supported_dialects.verified_expr(sql)
10816+ );
10817+
10818+ let sql = "a IS NOT JSON";
10819+ assert_eq!(
10820+ IsJson {
10821+ expr: Box::new(Identifier(Ident::new("a"))),
10822+ kind: None,
10823+ unique_keys: None,
10824+ negated: true,
10825+ },
10826+ supported_dialects.verified_expr(sql)
10827+ );
10828+
10829+ let sql = "a IS JSON VALUE";
10830+ assert_eq!(
10831+ IsJson {
10832+ expr: Box::new(Identifier(Ident::new("a"))),
10833+ kind: Some(JsonPredicateType::Value),
10834+ unique_keys: None,
10835+ negated: false,
10836+ },
10837+ supported_dialects.verified_expr(sql)
10838+ );
10839+
10840+ let sql = "a IS JSON SCALAR";
10841+ assert_eq!(
10842+ IsJson {
10843+ expr: Box::new(Identifier(Ident::new("a"))),
10844+ kind: Some(JsonPredicateType::Scalar),
10845+ unique_keys: None,
10846+ negated: false,
10847+ },
10848+ supported_dialects.verified_expr(sql)
10849+ );
10850+
10851+ let sql = "a IS JSON ARRAY";
10852+ assert_eq!(
10853+ IsJson {
10854+ expr: Box::new(Identifier(Ident::new("a"))),
10855+ kind: Some(JsonPredicateType::Array),
10856+ unique_keys: None,
10857+ negated: false,
10858+ },
10859+ supported_dialects.verified_expr(sql)
10860+ );
10861+
10862+ let sql = "a IS JSON OBJECT";
10863+ assert_eq!(
10864+ IsJson {
10865+ expr: Box::new(Identifier(Ident::new("a"))),
10866+ kind: Some(JsonPredicateType::Object),
10867+ unique_keys: None,
10868+ negated: false,
10869+ },
10870+ supported_dialects.verified_expr(sql)
10871+ );
10872+
10873+ let sql = "a IS JSON WITH UNIQUE KEYS";
10874+ assert_eq!(
10875+ IsJson {
10876+ expr: Box::new(Identifier(Ident::new("a"))),
10877+ kind: None,
10878+ unique_keys: Some(JsonKeyUniqueness::WithUniqueKeys),
10879+ negated: false,
10880+ },
10881+ supported_dialects.verified_expr(sql)
10882+ );
10883+
10884+ let sql = "a IS JSON WITHOUT UNIQUE KEYS";
10885+ assert_eq!(
10886+ IsJson {
10887+ expr: Box::new(Identifier(Ident::new("a"))),
10888+ kind: None,
10889+ unique_keys: Some(JsonKeyUniqueness::WithoutUniqueKeys),
10890+ negated: false,
10891+ },
10892+ supported_dialects.verified_expr(sql)
10893+ );
10894+
10895+ let sql = "a IS NOT JSON OBJECT WITHOUT UNIQUE KEYS";
10896+ assert_eq!(
10897+ IsJson {
10898+ expr: Box::new(Identifier(Ident::new("a"))),
10899+ kind: Some(JsonPredicateType::Object),
10900+ unique_keys: Some(JsonKeyUniqueness::WithoutUniqueKeys),
10901+ negated: true,
10902+ },
10903+ supported_dialects.verified_expr(sql)
10904+ );
10905+
10906+ supported_dialects.expr_parses_to("a IS JSON WITH UNIQUE", "a IS JSON WITH UNIQUE KEYS");
10907+ supported_dialects.expr_parses_to("a IS JSON WITHOUT UNIQUE", "a IS JSON WITHOUT UNIQUE KEYS");
10908+
10909+ assert_matches!(
10910+ supported_dialects.verified_expr("NOT a IS JSON"),
10911+ Expr::UnaryOp {
10912+ op: UnaryOperator::Not,
10913+ expr
10914+ } if matches!(&*expr, Expr::IsJson { .. })
10915+ );
10916+ }
10917+
10918+ #[test]
10919+ fn parse_is_json_predicate_unsupported_dialects() {
10920+ let unsupported_dialects = all_dialects_where(|d| !d.supports_is_json_predicate());
10921+ assert!(!unsupported_dialects.dialects.is_empty());
10922+
10923+ for sql in ["SELECT a IS JSON FROM t", "SELECT a IS NOT JSON FROM t"] {
10924+ let err = unsupported_dialects.parse_sql_statements(sql).unwrap_err();
10925+ let ParserError::ParserError(msg) = err else {
10926+ panic!("Expected ParserError::ParserError for `{sql}`, got: {err:?}");
10927+ };
10928+ assert!(
10929+ msg.contains("[NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS"),
10930+ "Unexpected error hint for unsupported dialects in `{sql}`: {msg}"
10931+ );
10932+ assert!(
10933+ !msg.contains("[NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT]"),
10934+ "Unsupported dialects should not advertise JSON IS-predicate syntax in `{sql}`: {msg}"
10935+ );
10936+ assert!(
10937+ msg.contains("found: JSON"),
10938+ "Expected parser to fail at JSON token for unsupported dialects in `{sql}`: {msg}"
10939+ );
10940+ }
10941+ }
10942+
10943+ #[test]
10944+ fn parse_is_json_predicate_negative() {
10945+ let supported_dialects = all_dialects_where(|d| d.supports_is_json_predicate());
10946+
10947+ let cases = [
10948+ (
10949+ "SELECT * FROM t WHERE a IS JSON WITH FROM",
10950+ &["Expected: UNIQUE", "found: FROM"][..],
10951+ ),
10952+ (
10953+ "SELECT * FROM t WHERE a IS JSON WITH KEYS",
10954+ &["Expected: UNIQUE", "found: KEYS"][..],
10955+ ),
10956+ (
10957+ "SELECT * FROM t WHERE a IS JSON WITHOUT FROM",
10958+ &["Expected: UNIQUE", "found: FROM"][..],
10959+ ),
10960+ (
10961+ "SELECT * FROM t WHERE a IS JSON WITHOUT KEYS",
10962+ &["Expected: UNIQUE", "found: KEYS"][..],
10963+ ),
10964+ (
10965+ "SELECT * FROM t WHERE a IS NOT JSON WITH FROM",
10966+ &["Expected: UNIQUE", "found: FROM"][..],
10967+ ),
10968+ (
10969+ "SELECT * FROM t WHERE a IS JSON VALUE ARRAY",
10970+ &["Expected: end of statement", "found: ARRAY"][..],
10971+ ),
10972+ (
10973+ "SELECT * FROM t WHERE a IS JSON OBJECT VALUE",
10974+ &["Expected: end of statement", "found: VALUE"][..],
10975+ ),
10976+ (
10977+ "SELECT * FROM t WHERE a IS JSON WITH UNIQUE EXTRA",
10978+ &["Expected: end of statement", "found: EXTRA"][..],
10979+ ),
10980+ (
10981+ "SELECT * FROM t WHERE a IS JSON WITH UNIQUE KEYS EXTRA",
10982+ &["Expected: end of statement", "found: EXTRA"][..],
10983+ ),
10984+ (
10985+ "SELECT * FROM t WHERE a IS JSON WITHOUT UNIQUE EXTRA",
10986+ &["Expected: end of statement", "found: EXTRA"][..],
10987+ ),
10988+ (
10989+ "SELECT * FROM t WHERE a IS JSON WITHOUT UNIQUE KEYS EXTRA",
10990+ &["Expected: end of statement", "found: EXTRA"][..],
10991+ ),
10992+ (
10993+ "SELECT * FROM t WHERE a IS JSON WITH UNIQUE KEYS WITH UNIQUE KEYS",
10994+ &["Expected: end of statement", "found: WITH"][..],
10995+ ),
10996+ (
10997+ "SELECT * FROM t WHERE a IS JSON WITHOUT UNIQUE KEYS WITHOUT UNIQUE KEYS",
10998+ &["Expected: end of statement", "found: WITHOUT"][..],
10999+ ),
11000+ ];
11001+
11002+ for (sql, expected_fragments) in cases {
11003+ let err = supported_dialects.parse_sql_statements(sql).unwrap_err();
11004+ let ParserError::ParserError(msg) = err else {
11005+ panic!("Expected ParserError::ParserError for `{sql}`, got: {err:?}");
11006+ };
11007+ for fragment in expected_fragments {
11008+ assert!(
11009+ msg.contains(fragment),
11010+ "Expected parser diagnostic for `{sql}` to contain `{fragment}`, got: {msg}"
11011+ );
11012+ }
11013+ }
11014+ }
11015+
1076611016#[test]
1076711017fn parse_discard() {
1076811018 let sql = "DISCARD ALL";
0 commit comments