Skip to content

Add PostgreSQL CREATE/ALTER TEXT SEARCH DDL Parsing#2250

Open
LucaCappelletti94 wants to merge 4 commits intoapache:mainfrom
LucaCappelletti94:postgres-regression-5
Open

Add PostgreSQL CREATE/ALTER TEXT SEARCH DDL Parsing#2250
LucaCappelletti94 wants to merge 4 commits intoapache:mainfrom
LucaCappelletti94:postgres-regression-5

Conversation

@LucaCappelletti94
Copy link
Copy Markdown
Contributor

Adds parser and AST support for PostgreSQL text search DDL statements:

  • CREATE TEXT SEARCH DICTIONARY ...
  • CREATE TEXT SEARCH CONFIGURATION ...
  • CREATE TEXT SEARCH TEMPLATE ...
  • CREATE TEXT SEARCH PARSER ...
  • ALTER TEXT SEARCH DICTIONARY ...
  • ALTER TEXT SEARCH CONFIGURATION ...
  • ALTER TEXT SEARCH TEMPLATE ...
  • ALTER TEXT SEARCH PARSER ...

The work also adds focused regression coverage for previously failing cases.

@LucaCappelletti94 LucaCappelletti94 marked this pull request as ready for review February 27, 2026 07:42
Comment thread src/parser/mod.rs Outdated
Comment on lines +5104 to +5108
if or_replace || or_alter || temporary || global.is_some() || transient || persistent {
return Err(ParserError::ParserError(
"CREATE TEXT SEARCH does not support CREATE modifiers".to_string(),
));
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if or_replace || or_alter || temporary || global.is_some() || transient || persistent {
return Err(ParserError::ParserError(
"CREATE TEXT SEARCH does not support CREATE modifiers".to_string(),
));
}

I think we can skip this validation and leave up to downstream crates if desired

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well this is not semantics, it would be constructing a syntax tree that is not currently valid syntax in any of the supported dialects. I have already encountered this genre of issue a few times and I am a bit confused as to which direction should be preferable.

You would prefer going for the permissive route?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we can have the parser be permissive in such cases

Comment thread src/parser/mod.rs Outdated
&& self.parse_one_of_keywords(&[Keyword::PERSISTENT]).is_some();
let create_view_params = self.parse_create_view_params()?;
if self.parse_keyword(Keyword::TABLE) {
if self.parse_keywords(&[Keyword::TEXT, Keyword::SEARCH]) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of parse, can we 'peek' TEXT, SEARCH? so that parse_create_text_search() can be somewhat standalone

Comment thread src/parser/mod.rs Outdated
let object_type = self.parse_text_search_object_type()?;
let name = self.parse_object_name(false)?;
self.expect_token(&Token::LParen)?;
let options = self.parse_comma_separated(Parser::parse_text_search_option)?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let options = self.parse_comma_separated(Parser::parse_text_search_option)?;
let options = self.parse_comma_separated(Parser::parse_sql_option)?;

I think we can reuse this parser given it matches the representation

Comment thread tests/sqlparser_postgres.rs Outdated
];

for sql in sql_cases {
if let Err(err) = pg().parse_sql_statements(sql) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can the tests use verified_statement, also pg_and_generic() where possible?

Comment thread tests/sqlparser_postgres.rs Outdated
Comment on lines +7938 to +7939
"CREATE TEXT SEARCH DICTIONARY alt_ts_dict1 (template=simple)",
"CREATE TEXT SEARCH DICTIONARY alt_ts_dict2 (template=simple)",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we do a pass through the test cases to remove duplicate/superfluous cases? (for example the first two highlighted here seem identical and expected to cover the same codepaths)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all distinct tests cases from the postgres regression corpus, I just included all of the associated ones. That being said, some really seem identical to each other. I will trim them down.

Introduce AST structures for CREATE/ALTER TEXT SEARCH object types\n(dictionary, configuration, template, parser), including display\nimplementations, statement variants, From conversions, and span wiring.
Add parser support for CREATE/ALTER TEXT SEARCH DICTIONARY,\nCONFIGURATION, TEMPLATE, and PARSER forms, including operation-specific\nALTER clauses and strict CREATE option parsing.\n\nRegister text-search object names as parser keywords and reject unsupported\nCREATE modifiers for text-search objects.
Add regression coverage for the provided CREATE/ALTER TEXT SEARCH\nstatements and guardrails for rejected forms (quoted object type,\nmissing key/value option syntax, and unsupported CREATE modifiers).
Comment thread src/ast/ddl.rs
}
}

/// PostgreSQL text search object kind.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// PostgreSQL text search object kind.
/// Text search object kind.

Can we instead add a [PostgreSQL] link to the reference docs. We can avoid mentioning a specific dialect as part of the main description (it goes stale quickly/immediately if there are other dialects that support the feature)

Comment thread src/ast/ddl.rs
}
}

/// PostgreSQL `CREATE TEXT SEARCH ...` statement.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// PostgreSQL `CREATE TEXT SEARCH ...` statement.
/// `CREATE TEXT SEARCH ...` statement.

same comment regarding doc link

Comment thread src/ast/ddl.rs
}
}

/// Operation for PostgreSQL `ALTER TEXT SEARCH ...`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Operation for PostgreSQL `ALTER TEXT SEARCH ...`.
/// Operation for `ALTER TEXT SEARCH ...`.

same comment regarding doc link

Comment thread src/ast/ddl.rs
}
}

/// Option assignment used by `ALTER TEXT SEARCH DICTIONARY ... ( ... )`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a link to the docs for this struct?

Comment thread src/ast/ddl.rs
}
}

/// PostgreSQL `ALTER TEXT SEARCH ...` statement.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// PostgreSQL `ALTER TEXT SEARCH ...` statement.
/// `ALTER TEXT SEARCH ...` statement.

same comment regarding doc link

Comment thread src/parser/mod.rs
Keyword::CONFIGURATION => Ok(TextSearchObjectType::Configuration),
Keyword::TEMPLATE => Ok(TextSearchObjectType::Template),
Keyword::PARSER => Ok(TextSearchObjectType::Parser),
// unreachable because expect_one_of_keywords used above
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// unreachable because expect_one_of_keywords used above

Comment thread src/parser/mod.rs
Ok(AlterTextSearchDictionaryOption { key, value })
}

/// Parse a PostgreSQL `ALTER TEXT SEARCH ...` statement.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Parse a PostgreSQL `ALTER TEXT SEARCH ...` statement.
/// Parse a `ALTER TEXT SEARCH ...` statement.

}

#[test]
fn parse_create_and_alter_text_search() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we split this into parse_create_text_search and parse_alter_text_search functions? since they're different syntax

);

// CREATE with quoted option key
pg_and_generic().verified_stmt("CREATE TEXT SEARCH TEMPLATE t (\"Init\" = init_function)");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the text strings, we can use a raw string literal to avoid manually escaping quotes

Comment thread src/parser/mod.rs
Comment on lines +5267 to +5275
if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
AlterTextSearchOperation::RenameTo {
new_name: self.parse_identifier()?,
}
} else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) {
AlterTextSearchOperation::OwnerTo(self.parse_owner()?)
} else if self.parse_keywords(&[Keyword::SET, Keyword::SCHEMA]) {
AlterTextSearchOperation::SetSchema {
schema_name: self.parse_object_name(false)?,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like these clauses are duplicated for each object type? if so it doesn't seem like we need to make the clauses per object type, we can parse which ever ones show up and if a downstream crate needs to validate which clauses are valid for which object type they can explicitly do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants