mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-10-09 21:42:05 +00:00
Parse SET NAMES syntax in Postgres (#1752)
This commit is contained in:
parent
a629ddf89b
commit
9e09b617e8
8 changed files with 39 additions and 12 deletions
|
@ -2956,10 +2956,8 @@ pub enum Statement {
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// SET NAMES 'charset_name' [COLLATE 'collation_name']
|
/// SET NAMES 'charset_name' [COLLATE 'collation_name']
|
||||||
/// ```
|
/// ```
|
||||||
///
|
|
||||||
/// Note: this is a MySQL-specific statement.
|
|
||||||
SetNames {
|
SetNames {
|
||||||
charset_name: String,
|
charset_name: Ident,
|
||||||
collation_name: Option<String>,
|
collation_name: Option<String>,
|
||||||
},
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
|
@ -4684,8 +4682,7 @@ impl fmt::Display for Statement {
|
||||||
charset_name,
|
charset_name,
|
||||||
collation_name,
|
collation_name,
|
||||||
} => {
|
} => {
|
||||||
f.write_str("SET NAMES ")?;
|
write!(f, "SET NAMES {}", charset_name)?;
|
||||||
f.write_str(charset_name)?;
|
|
||||||
|
|
||||||
if let Some(collation) = collation_name {
|
if let Some(collation) = collation_name {
|
||||||
f.write_str(" COLLATE ")?;
|
f.write_str(" COLLATE ")?;
|
||||||
|
|
|
@ -155,4 +155,8 @@ impl Dialect for GenericDialect {
|
||||||
fn supports_match_against(&self) -> bool {
|
fn supports_match_against(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn supports_set_names(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -980,6 +980,16 @@ pub trait Dialect: Debug + Any {
|
||||||
fn supports_order_by_all(&self) -> bool {
|
fn supports_order_by_all(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the dialect supports `SET NAMES <charset_name> [COLLATE <collation_name>]`.
|
||||||
|
///
|
||||||
|
/// - [MySQL](https://dev.mysql.com/doc/refman/8.4/en/set-names.html)
|
||||||
|
/// - [Postgres](https://www.postgresql.org/docs/17/sql-set.html)
|
||||||
|
///
|
||||||
|
/// Note: Postgres doesn't support the `COLLATE` clause, but we permissively parse it anyway.
|
||||||
|
fn supports_set_names(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This represents the operators for which precedence must be defined
|
/// This represents the operators for which precedence must be defined
|
||||||
|
|
|
@ -137,6 +137,10 @@ impl Dialect for MySqlDialect {
|
||||||
fn supports_match_against(&self) -> bool {
|
fn supports_match_against(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn supports_set_names(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `LOCK TABLES`
|
/// `LOCK TABLES`
|
||||||
|
|
|
@ -254,4 +254,8 @@ impl Dialect for PostgreSqlDialect {
|
||||||
fn supports_geometric_types(&self) -> bool {
|
fn supports_geometric_types(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn supports_set_names(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10962,14 +10962,14 @@ impl<'a> Parser<'a> {
|
||||||
OneOrManyWithParens::One(self.parse_object_name(false)?)
|
OneOrManyWithParens::One(self.parse_object_name(false)?)
|
||||||
};
|
};
|
||||||
|
|
||||||
if matches!(&variables, OneOrManyWithParens::One(variable) if variable.to_string().eq_ignore_ascii_case("NAMES")
|
let names = matches!(&variables, OneOrManyWithParens::One(variable) if variable.to_string().eq_ignore_ascii_case("NAMES"));
|
||||||
&& dialect_of!(self is MySqlDialect | GenericDialect))
|
|
||||||
{
|
if names && self.dialect.supports_set_names() {
|
||||||
if self.parse_keyword(Keyword::DEFAULT) {
|
if self.parse_keyword(Keyword::DEFAULT) {
|
||||||
return Ok(Statement::SetNamesDefault {});
|
return Ok(Statement::SetNamesDefault {});
|
||||||
}
|
}
|
||||||
|
|
||||||
let charset_name = self.parse_literal_string()?;
|
let charset_name = self.parse_identifier()?;
|
||||||
let collation_name = if self.parse_one_of_keywords(&[Keyword::COLLATE]).is_some() {
|
let collation_name = if self.parse_one_of_keywords(&[Keyword::COLLATE]).is_some() {
|
||||||
Some(self.parse_literal_string()?)
|
Some(self.parse_literal_string()?)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14631,3 +14631,11 @@ fn parse_array_type_def_with_brackets() {
|
||||||
dialects.verified_stmt("SELECT x::INT[]");
|
dialects.verified_stmt("SELECT x::INT[]");
|
||||||
dialects.verified_stmt("SELECT STRING_TO_ARRAY('1,2,3', ',')::INT[3]");
|
dialects.verified_stmt("SELECT STRING_TO_ARRAY('1,2,3', ',')::INT[3]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_set_names() {
|
||||||
|
let dialects = all_dialects_where(|d| d.supports_set_names());
|
||||||
|
dialects.verified_stmt("SET NAMES 'UTF8'");
|
||||||
|
dialects.verified_stmt("SET NAMES 'utf8'");
|
||||||
|
dialects.verified_stmt("SET NAMES UTF8 COLLATE bogus");
|
||||||
|
}
|
||||||
|
|
|
@ -2696,7 +2696,7 @@ fn parse_set_names() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetNames {
|
Statement::SetNames {
|
||||||
charset_name: "utf8mb4".to_string(),
|
charset_name: "utf8mb4".into(),
|
||||||
collation_name: None,
|
collation_name: None,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -2705,7 +2705,7 @@ fn parse_set_names() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
Statement::SetNames {
|
Statement::SetNames {
|
||||||
charset_name: "utf8mb4".to_string(),
|
charset_name: "utf8mb4".into(),
|
||||||
collation_name: Some("bogus".to_string()),
|
collation_name: Some("bogus".to_string()),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -2716,7 +2716,7 @@ fn parse_set_names() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmt,
|
stmt,
|
||||||
vec![Statement::SetNames {
|
vec![Statement::SetNames {
|
||||||
charset_name: "utf8mb4".to_string(),
|
charset_name: "utf8mb4".into(),
|
||||||
collation_name: Some("bogus".to_string()),
|
collation_name: Some("bogus".to_string()),
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue