@@ -506,7 +506,6 @@ impl<'a> Parser<'a> {
506506
507507 match &self.peek_token_ref().token {
508508 Token::EOF => break,
509-
510509 // end of statement
511510 Token::Word(word)
512511 if expecting_statement_delimiter && word.keyword == Keyword::END =>
@@ -3986,13 +3985,23 @@ impl<'a> Parser<'a> {
39863985 {
39873986 let expr2 = self.parse_expr()?;
39883987 Ok(Expr::IsNotDistinctFrom(Box::new(expr), Box::new(expr2)))
3988+ } else if self.dialect.supports_is_json_predicate()
3989+ && self.parse_keyword(Keyword::JSON)
3990+ {
3991+ self.parse_is_json_predicate(expr, false)
3992+ } else if self.dialect.supports_is_json_predicate()
3993+ && self.parse_keywords(&[Keyword::NOT, Keyword::JSON])
3994+ {
3995+ self.parse_is_json_predicate(expr, true)
39893996 } else if let Ok(is_normalized) = self.parse_unicode_is_normalized(expr) {
39903997 Ok(is_normalized)
39913998 } else {
3992- self.expected_ref(
3993- "[NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS",
3994- self.peek_token_ref(),
3995- )
3999+ let expected = if self.dialect.supports_is_json_predicate() {
4000+ "[NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS"
4001+ } else {
4002+ "[NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS"
4003+ };
4004+ self.expected_ref(expected, self.peek_token_ref())
39964005 }
39974006 }
39984007 Keyword::AT => {
@@ -8442,6 +8451,7 @@ impl<'a> Parser<'a> {
84428451 char: self.parse_identifier()?,
84438452 });
84448453 }
8454+ Some(Keyword::NULL) => break,
84458455 _ => {
84468456 break;
84478457 }
@@ -12237,6 +12247,43 @@ impl<'a> Parser<'a> {
1223712247 }
1223812248 }
1223912249
12250+ /// Parse the `IS [NOT] JSON` predicate after `JSON` (and optional `NOT`) was consumed.
12251+ fn parse_is_json_predicate(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
12252+ let kind = match self.parse_one_of_keywords(&[
12253+ Keyword::VALUE,
12254+ Keyword::SCALAR,
12255+ Keyword::ARRAY,
12256+ Keyword::OBJECT,
12257+ ]) {
12258+ Some(Keyword::VALUE) => Some(JsonPredicateType::Value),
12259+ Some(Keyword::SCALAR) => Some(JsonPredicateType::Scalar),
12260+ Some(Keyword::ARRAY) => Some(JsonPredicateType::Array),
12261+ Some(Keyword::OBJECT) => Some(JsonPredicateType::Object),
12262+ _ => None,
12263+ };
12264+
12265+ let unique_keys = match self.parse_one_of_keywords(&[Keyword::WITH, Keyword::WITHOUT]) {
12266+ Some(Keyword::WITH) => {
12267+ self.expect_keyword_is(Keyword::UNIQUE)?;
12268+ let _ = self.parse_keyword(Keyword::KEYS);
12269+ Some(JsonKeyUniqueness::WithUniqueKeys)
12270+ }
12271+ Some(Keyword::WITHOUT) => {
12272+ self.expect_keyword_is(Keyword::UNIQUE)?;
12273+ let _ = self.parse_keyword(Keyword::KEYS);
12274+ Some(JsonKeyUniqueness::WithoutUniqueKeys)
12275+ }
12276+ _ => None,
12277+ };
12278+
12279+ Ok(Expr::IsJson {
12280+ expr: Box::new(expr),
12281+ kind,
12282+ unique_keys,
12283+ negated,
12284+ })
12285+ }
12286+
1224012287 /// Parse a literal unicode normalization clause
1224112288 pub fn parse_unicode_is_normalized(&mut self, expr: Expr) -> Result<Expr, ParserError> {
1224212289 let neg = self.parse_keyword(Keyword::NOT);
@@ -21218,12 +21265,35 @@ mod tests {
2121821265 assert_eq!(
2121921266 ast,
2122021267 Err(ParserError::ParserError(
21221- "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: a at Line: 1, Column: 16"
21268+ "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [ form] NORMALIZED FROM after IS, found: a at Line: 1, Column: 16"
2122221269 .to_string()
2122321270 ))
2122421271 );
2122521272 }
2122621273
21274+ #[test]
21275+ fn test_is_predicate_error_hint_depends_on_dialect() {
21276+ let sql = "SELECT this is a syntax error";
21277+
21278+ let generic_err = Parser::parse_sql(&GenericDialect, sql).unwrap_err();
21279+ let ParserError::ParserError(generic_msg) = generic_err else {
21280+ panic!("Expected ParserError::ParserError, got: {generic_err:?}");
21281+ };
21282+ assert!(
21283+ generic_msg.contains("[NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT]"),
21284+ "Expected Generic dialect to include JSON predicate hint, got: {generic_msg}"
21285+ );
21286+
21287+ let mysql_err = Parser::parse_sql(&MySqlDialect {}, sql).unwrap_err();
21288+ let ParserError::ParserError(mysql_msg) = mysql_err else {
21289+ panic!("Expected ParserError::ParserError, got: {mysql_err:?}");
21290+ };
21291+ assert!(
21292+ !mysql_msg.contains("[NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT]"),
21293+ "Expected MySQL dialect to exclude JSON predicate hint, got: {mysql_msg}"
21294+ );
21295+ }
21296+
2122721297 #[test]
2122821298 fn test_nested_explain_error() {
2122921299 let sql = "EXPLAIN EXPLAIN SELECT 1";
0 commit comments