Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions src/ast/ddl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5757,3 +5757,133 @@ impl From<AlterPolicy> for crate::ast::Statement {
crate::ast::Statement::AlterPolicy(v)
}
}

/// `CREATE TEXT SEARCH CONFIGURATION` statement.
///
/// Note: this is a PostgreSQL-specific statement.
/// <https://www.postgresql.org/docs/current/sql-createtsconfig.html>
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct CreateTextSearchConfiguration {
/// Name of the text search configuration being created.
pub name: ObjectName,
/// Options list. PostgreSQL requires `PARSER = parser_name`; the
/// parser does not enforce required keys (matching other options-list
/// handling in this crate).
pub options: Vec<SqlOption>,
}

impl fmt::Display for CreateTextSearchConfiguration {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"CREATE TEXT SEARCH CONFIGURATION {name} ({options})",
name = self.name,
options = display_comma_separated(&self.options),
)
}
}

impl From<CreateTextSearchConfiguration> for crate::ast::Statement {
fn from(v: CreateTextSearchConfiguration) -> Self {
crate::ast::Statement::CreateTextSearchConfiguration(v)
}
}

/// `CREATE TEXT SEARCH DICTIONARY` statement.
///
/// Note: this is a PostgreSQL-specific statement.
/// <https://www.postgresql.org/docs/current/sql-createtsdictionary.html>
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct CreateTextSearchDictionary {
/// Name of the text search dictionary being created.
pub name: ObjectName,
/// Options list. PostgreSQL requires `TEMPLATE = template_name`; the
/// parser does not enforce required keys.
pub options: Vec<SqlOption>,
}

impl fmt::Display for CreateTextSearchDictionary {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"CREATE TEXT SEARCH DICTIONARY {name} ({options})",
name = self.name,
options = display_comma_separated(&self.options),
)
}
}

impl From<CreateTextSearchDictionary> for crate::ast::Statement {
fn from(v: CreateTextSearchDictionary) -> Self {
crate::ast::Statement::CreateTextSearchDictionary(v)
}
}

/// `CREATE TEXT SEARCH PARSER` statement.
///
/// Note: this is a PostgreSQL-specific statement.
/// <https://www.postgresql.org/docs/current/sql-createtsparser.html>
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct CreateTextSearchParser {
/// Name of the text search parser being created.
pub name: ObjectName,
/// Options list. PostgreSQL requires `START`, `GETTOKEN`, `END`, and
/// `LEXTYPES` (with `HEADLINE` optional); the parser does not enforce
/// required keys.
pub options: Vec<SqlOption>,
}

impl fmt::Display for CreateTextSearchParser {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"CREATE TEXT SEARCH PARSER {name} ({options})",
name = self.name,
options = display_comma_separated(&self.options),
)
}
}

impl From<CreateTextSearchParser> for crate::ast::Statement {
fn from(v: CreateTextSearchParser) -> Self {
crate::ast::Statement::CreateTextSearchParser(v)
}
}

/// `CREATE TEXT SEARCH TEMPLATE` statement.
///
/// Note: this is a PostgreSQL-specific statement.
/// <https://www.postgresql.org/docs/current/sql-createtstemplate.html>
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct CreateTextSearchTemplate {
/// Name of the text search template being created.
pub name: ObjectName,
/// Options list. PostgreSQL requires `LEXIZE` (with `INIT` optional);
/// the parser does not enforce required keys.
pub options: Vec<SqlOption>,
}

impl fmt::Display for CreateTextSearchTemplate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"CREATE TEXT SEARCH TEMPLATE {name} ({options})",
name = self.name,
options = display_comma_separated(&self.options),
)
}
}

impl From<CreateTextSearchTemplate> for crate::ast::Statement {
fn from(v: CreateTextSearchTemplate) -> Self {
crate::ast::Statement::CreateTextSearchTemplate(v)
}
}
31 changes: 30 additions & 1 deletion src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ pub use self::ddl::{
ColumnPolicyProperty, ConstraintCharacteristics, CreateCollation, CreateCollationDefinition,
CreateConnector, CreateDomain, CreateExtension, CreateFunction, CreateIndex, CreateOperator,
CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
CreateTable, CreateTrigger, CreateView, Deduplicate, DeferrableInitial, DistStyle,
CreateTable, CreateTextSearchConfiguration, CreateTextSearchDictionary, CreateTextSearchParser,
CreateTextSearchTemplate, CreateTrigger, CreateView, Deduplicate, DeferrableInitial, DistStyle,
DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily,
DropOperatorSignature, DropPolicy, DropTrigger, ForValues, FunctionReturnType, GeneratedAs,
GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
Expand Down Expand Up @@ -4013,6 +4014,30 @@ pub enum Statement {
/// <https://www.postgresql.org/docs/current/sql-createcollation.html>
CreateCollation(CreateCollation),
/// ```sql
/// CREATE TEXT SEARCH CONFIGURATION name ( PARSER = parser_name )
/// ```
/// Note: this is a PostgreSQL-specific statement.
/// <https://www.postgresql.org/docs/current/sql-createtsconfig.html>
CreateTextSearchConfiguration(CreateTextSearchConfiguration),
/// ```sql
/// CREATE TEXT SEARCH DICTIONARY name ( TEMPLATE = template_name [, option = value, ...] )
/// ```
/// Note: this is a PostgreSQL-specific statement.
/// <https://www.postgresql.org/docs/current/sql-createtsdictionary.html>
CreateTextSearchDictionary(CreateTextSearchDictionary),
/// ```sql
/// CREATE TEXT SEARCH PARSER name ( START = start_fn, GETTOKEN = gettoken_fn, END = end_fn, LEXTYPES = lextypes_fn [, HEADLINE = headline_fn] )
/// ```
/// Note: this is a PostgreSQL-specific statement.
/// <https://www.postgresql.org/docs/current/sql-createtsparser.html>
CreateTextSearchParser(CreateTextSearchParser),
/// ```sql
/// CREATE TEXT SEARCH TEMPLATE name ( [INIT = init_fn,] LEXIZE = lexize_fn )
/// ```
/// Note: this is a PostgreSQL-specific statement.
/// <https://www.postgresql.org/docs/current/sql-createtstemplate.html>
CreateTextSearchTemplate(CreateTextSearchTemplate),
/// ```sql
/// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
/// ```
/// Note: this is a PostgreSQL-specific statement.
Expand Down Expand Up @@ -5495,6 +5520,10 @@ impl fmt::Display for Statement {
Statement::CreateIndex(create_index) => create_index.fmt(f),
Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
Statement::CreateTextSearchConfiguration(v) => write!(f, "{v}"),
Statement::CreateTextSearchDictionary(v) => write!(f, "{v}"),
Statement::CreateTextSearchParser(v) => write!(f, "{v}"),
Statement::CreateTextSearchTemplate(v) => write!(f, "{v}"),
Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
Statement::DropOperatorFamily(drop_operator_family) => {
Expand Down
8 changes: 8 additions & 0 deletions src/ast/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ impl Spanned for Values {
/// - [Statement::Declare]
/// - [Statement::CreateExtension]
/// - [Statement::CreateCollation]
/// - [Statement::CreateTextSearchConfiguration]
/// - [Statement::CreateTextSearchDictionary]
/// - [Statement::CreateTextSearchParser]
/// - [Statement::CreateTextSearchTemplate]
/// - [Statement::AlterCollation]
/// - [Statement::Fetch]
/// - [Statement::Flush]
Expand Down Expand Up @@ -387,6 +391,10 @@ impl Spanned for Statement {
Statement::CreateRole(create_role) => create_role.span(),
Statement::CreateExtension(create_extension) => create_extension.span(),
Statement::CreateCollation(create_collation) => create_collation.span(),
Statement::CreateTextSearchConfiguration(stmt) => stmt.name.span(),
Statement::CreateTextSearchDictionary(stmt) => stmt.name.span(),
Statement::CreateTextSearchParser(stmt) => stmt.name.span(),
Statement::CreateTextSearchTemplate(stmt) => stmt.name.span(),
Statement::DropExtension(drop_extension) => drop_extension.span(),
Statement::DropOperator(drop_operator) => drop_operator.span(),
Statement::DropOperatorFamily(drop_operator_family) => drop_operator_family.span(),
Expand Down
4 changes: 4 additions & 0 deletions src/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ define_keywords!(
COMPUTE,
CONCURRENTLY,
CONDITION,
CONFIGURATION,
CONFLICT,
CONNECT,
CONNECTION,
Expand Down Expand Up @@ -333,6 +334,7 @@ define_keywords!(
DETACH,
DETAIL,
DETERMINISTIC,
DICTIONARY,
DIMENSIONS,
DIRECTORY,
DISABLE,
Expand Down Expand Up @@ -765,6 +767,7 @@ define_keywords!(
PARALLEL,
PARAMETER,
PARQUET,
PARSER,
PART,
PARTIAL,
PARTITION,
Expand Down Expand Up @@ -1035,6 +1038,7 @@ define_keywords!(
TASK,
TBLPROPERTIES,
TEMP,
TEMPLATE,
TEMPORARY,
TEMPTABLE,
TERMINATED,
Expand Down
48 changes: 48 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5212,6 +5212,8 @@ impl<'a> Parser<'a> {
}
} else if self.parse_keyword(Keyword::SERVER) {
self.parse_pg_create_server()
} else if self.parse_keywords(&[Keyword::TEXT, Keyword::SEARCH]) {
self.parse_create_text_search()
} else {
self.expected_ref("an object type after CREATE", self.peek_token_ref())
}
Expand Down Expand Up @@ -8176,6 +8178,52 @@ impl<'a> Parser<'a> {
})
}

/// Parse a PostgreSQL-specific `CREATE TEXT SEARCH CONFIGURATION | DICTIONARY | PARSER | TEMPLATE` statement.
pub fn parse_create_text_search(&mut self) -> Result<Statement, ParserError> {
let subtype = if self.parse_keyword(Keyword::CONFIGURATION) {
Keyword::CONFIGURATION
} else if self.parse_keyword(Keyword::DICTIONARY) {
Keyword::DICTIONARY
} else if self.parse_keyword(Keyword::PARSER) {
Keyword::PARSER
} else if self.parse_keyword(Keyword::TEMPLATE) {
Keyword::TEMPLATE
} else {
return self.expected_ref(
"CONFIGURATION, DICTIONARY, PARSER, or TEMPLATE after CREATE TEXT SEARCH",
self.peek_token_ref(),
);
};

let name = self.parse_object_name(false)?;
self.expect_token(&Token::LParen)?;
let options = self.parse_comma_separated(Parser::parse_sql_option)?;
self.expect_token(&Token::RParen)?;

Ok(match subtype {
Keyword::CONFIGURATION => {
Statement::CreateTextSearchConfiguration(CreateTextSearchConfiguration {
name,
options,
})
}
Keyword::DICTIONARY => {
Statement::CreateTextSearchDictionary(CreateTextSearchDictionary { name, options })
}
Keyword::PARSER => {
Statement::CreateTextSearchParser(CreateTextSearchParser { name, options })
}
Keyword::TEMPLATE => {
Statement::CreateTextSearchTemplate(CreateTextSearchTemplate { name, options })
}
unexpected => {
return Err(ParserError::ParserError(format!(
"Internal parser error: unexpected CREATE TEXT SEARCH subtype `{unexpected}`"
)))
}
})
}

/// Parse a PostgreSQL-specific [Statement::DropExtension] statement.
pub fn parse_drop_extension(&mut self) -> Result<Statement, ParserError> {
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
Expand Down
Loading
Loading