@@ -1687,6 +1687,16 @@ impl<'a> Parser<'a> {
16871687 }
16881688 }
16891689
1690+ /// Returns true if the given [ObjectName] is a single unquoted
1691+ /// identifier matching `expected` (case-insensitive).
1692+ fn is_simple_unquoted_object_name(name: &ObjectName, expected: &str) -> bool {
1693+ if let [ObjectNamePart::Identifier(ident)] = name.0.as_slice() {
1694+ ident.quote_style.is_none() && ident.value.eq_ignore_ascii_case(expected)
1695+ } else {
1696+ false
1697+ }
1698+ }
1699+
16901700 /// Parse an expression prefix.
16911701 pub fn parse_prefix(&mut self) -> Result<Expr, ParserError> {
16921702 // allow the dialect to override prefix parsing
@@ -1720,7 +1730,21 @@ impl<'a> Parser<'a> {
17201730 // so given `NOT 'a' LIKE 'b'`, we'd accept `NOT` as a possible custom data type
17211731 // name, resulting in `NOT 'a'` being recognized as a `TypedString` instead of
17221732 // an unary negation `NOT ('a' LIKE 'b')`. To solve this, we don't accept the
1723- // `type 'string'` syntax for the custom data types at all.
1733+ // `type 'string'` syntax for the custom data types at all ...
1734+ //
1735+ // ... with the exception of `xml '...'` on dialects that support XML
1736+ // expressions, which is a valid PostgreSQL typed string literal.
1737+ DataType::Custom(ref name, ref modifiers)
1738+ if modifiers.is_empty()
1739+ && Self::is_simple_unquoted_object_name(name, "xml")
1740+ && parser.dialect.supports_xml_expressions() =>
1741+ {
1742+ Ok(Expr::TypedString(TypedString {
1743+ data_type: DataType::Custom(name.clone(), modifiers.clone()),
1744+ value: parser.parse_value()?,
1745+ uses_odbc_syntax: false,
1746+ }))
1747+ }
17241748 DataType::Custom(..) => parser_err!("dummy", loc),
17251749 // MySQL supports using the `BINARY` keyword as a cast to binary type.
17261750 DataType::Binary(..) if self.dialect.supports_binary_kw_as_cast() => {
0 commit comments