feat(spi): add quoteIdentifierAlways to ISQLIdentifierProcessor - #2234
Conversation
…chema and table in REFERENCES Replaces direct " concatenation with the dialect-specific processor: PostgreSQLMetaData.POSTGRE_SQL_IDENTIFIER_PROCESSOR and KingBaseMetaData.KINGBASE_SQL_IDENTIFIER_PROCESSOR. Built on the SPI extension (OtterMind#2234). Closes OtterMind#2187 (superseded by this SPI-based approach) Co-Authored-By: Claude <noreply@anthropic.com>
6c6f341 to
4630a50
Compare
Replaces direct backtick concatenation with KingBaseMetaData.KINGBASE_SQL_IDENTIFIER_PROCESSOR.quoteIdentifierAlways, per the maintainer review on OtterMind#2187. Built on the SPI extension (OtterMind#2234). Closes OtterMind#2145 (superseded by this SPI-based approach) Co-Authored-By: Claude <noreply@anthropic.com>
…ENAME Replaces direct " concatenation with SnowflakeMetaData.SNOWFLAKE_SQL_IDENTIFIER_PROCESSOR.quoteIdentifierAlways for DROP COLUMN, CREATE TABLE schema qualifier, and RENAME COLUMN. CHANGE COLUMN (MySQL syntax) is replaced with RENAME COLUMN (Snowflake). Built on the SPI extension (OtterMind#2234). Closes OtterMind#2169, OtterMind#2185, OtterMind#2186 (superseded by this SPI-based approach) Co-Authored-By: Claude <noreply@anthropic.com>
…chema and table in REFERENCES Replaces direct " concatenation with the dialect-specific processor: PostgreSQLMetaData.POSTGRE_SQL_IDENTIFIER_PROCESSOR and KingBaseMetaData.KINGBASE_SQL_IDENTIFIER_PROCESSOR. Built on the SPI extension (OtterMind#2234). Closes OtterMind#2187 (superseded by this SPI-based approach) Co-Authored-By: Claude <noreply@anthropic.com>
|
Fixed the CI failure: the test mock class |
openai0229
left a comment
There was a problem hiding this comment.
The shared SPI direction and delimiter round-trip tests are good, but this is not ready to merge yet. ISQLIdentifierProcessor is the public plugin SPI; adding a new non-default abstract method is source-incompatible for external implementations. Please provide a backward-compatible default or capability/versioned migration path and test that compatibility. This PR also changes removeIdentifierQuote semantics used by SQL parsing/completion callers, so add regression coverage at those caller boundaries rather than only direct processor round-trip tests.
4630a50 to
dcb7cad
Compare
|
Changed |
Add a new SPI method that unconditionally quotes an identifier, preserving the exact name regardless of case or keyword status. Embedded delimiter characters are escaped per the dialect convention (double-quote "" for ", backtick `` for `, bracket ]] for ]). Fix removeIdentifierQuote to unescape doubled delimiters, satisfying the round-trip contract: removeIdentifierQuote(quoteIdentifierAlways(raw)).equals(raw). Implementations: - DefaultSQLIdentifierProcessor: double-quote + escape " -> "" - MysqlIdentifierProcessor: backtick + escape ` -> `` - SqlServerIdentifierProcessor: bracket + escape ] -> ]] Also add SNOWFLAKE_SQL_IDENTIFIER_PROCESSOR static field to SnowflakeMetaData, mirroring PostgreSQL/KingBase, to give Snowflake column-type enums access to the processor for downstream quoting PRs. Tests: 36 tests covering conditional vs always-quote, embedded delimiters, round-trip, reserved keywords, and case preservation across Default, MySQL, and SqlServer processors. Addresses the maintainer review on OtterMind#2187 requesting the shared SPI contract be extended before rebasing the individual dialect quoting PRs. Co-Authored-By: Claude <noreply@anthropic.com>
dcb7cad to
85fe1ff
Compare
openai0229
left a comment
There was a problem hiding this comment.
Maintainer follow-up completed on the original branch:
- rebased onto current
main; - kept the SPI source-compatible with a default method;
- made the fallback fail fast when an external processor cannot actually quote unconditionally;
- preserved the quote/remove round-trip for embedded delimiters;
- removed the unrelated Snowflake constant;
- added parser and completion caller-boundary regressions plus a legacy-implementation compatibility test.
Verification: the full test suites for chat2db-community-spi, chat2db-community-domain-core, chat2db-community-mysql, and chat2db-community-sqlserver passed with maven.test.skip=false and skipTests=false.
Summary
Addresses the maintainer review on #2187 requesting the shared SPI contract be extended before rebasing the individual dialect quoting PRs.
Adds
quoteIdentifierAlways(String)toISQLIdentifierProcessor— an unconditional quoting method that preserves the exact identifier name regardless of case or keyword status. Embedded delimiter characters are escaped per the dialect convention. Also fixesremoveIdentifierQuoteto unescape doubled delimiters, satisfying the round-trip contract:removeIdentifierQuote(quoteIdentifierAlways(raw)).equals(raw).Changes
SPI Interface (
ISQLIdentifierProcessor)quoteIdentifierAlways(String)— always quotes, preserves exact case, escapes embedded delimitersDefault Implementation (
DefaultSQLIdentifierProcessor)quoteIdentifierAlways: wraps in"...", escapes"→""removeIdentifierQuote: replaced regex-based approach with strip-and-unescape (handles""→")Dialect Overrides
""→""`→``[...]]→]]PostgreSQL, KingBase, Oracle, DM, Oscar, SQLite all use
"— inherit from Default without override.Snowflake Accessor
SNOWFLAKE_SQL_IDENTIFIER_PROCESSORstatic field toSnowflakeMetaData, mirroring PostgreSQL'sPOSTGRE_SQL_IDENTIFIER_PROCESSORand KingBase'sKINGBASE_SQL_IDENTIFIER_PROCESSOR. This gives Snowflake column-type enums access to the processor for downstream quoting PRs.Tests (36 tests, all passing)
DefaultSQLIdentifierProcessorTest(16 tests)quoteIdentifierAlways: wraps simple name, preserves mixed case, escapes embedded", handles null, handles reserved keywordsquoteIdentifier(conditional): doesn't quote lowercase valid, quotes invalidremoveIdentifierQuote: strips and unescapes, passes through unquotedquoteIdentifierAlways→removeIdentifierQuoterestores raw (tested with plain, mixed-case, embedded delimiter, reserved keyword, empty)MysqlIdentifierProcessorTest(10 tests)quoteIdentifierAlways: wraps in backtick, escapes embedded backtick, preserves mixed caseremoveIdentifierQuote: strips backtick + double-quote, unescapesSqlServerIdentifierProcessorTest(10 tests)quoteIdentifierAlways: wraps in brackets, escapes embedded]removeIdentifierQuote: strips brackets + double-quote, unescapesVerification
Downstream (Phase 2)
Once this SPI extension merges, the 5 quoting PRs (#2145, #2169, #2185, #2186, #2187) will be reworked to use
processor.quoteIdentifierAlways(name)instead of direct"concatenation:KingBaseMetaData.KINGBASE_SQL_IDENTIFIER_PROCESSOR.quoteIdentifierAlways(name)SnowflakeMetaData.SNOWFLAKE_SQL_IDENTIFIER_PROCESSOR.quoteIdentifierAlways(name)SnowflakeMetaData.SNOWFLAKE_SQL_IDENTIFIER_PROCESSOR.quoteIdentifierAlways(schemaName)quoteIdentifierAlways(oldName)+quoteIdentifierAlways(newName)in RENAME COLUMNPostgreSQLMetaData.POSTGRE_SQL_IDENTIFIER_PROCESSOR/KingBaseMetaData.KINGBASE_SQL_IDENTIFIER_PROCESSORContributor declaration
AI assistance: The implementation, tests, verification, and PR description were produced with Claude Code assistance.