refactor(isthmus): derive CREATE-statement table types from the provider - #1050
Open
nielspardon wants to merge 1 commit into
Open
refactor(isthmus): derive CREATE-statement table types from the provider#1050nielspardon wants to merge 1 commit into
nielspardon wants to merge 1 commit into
Conversation
The builder work threaded the ConverterProvider into the CalciteCatalogReader construction, but the type derivation underneath still used global defaults on that same injected path: - createSubstraitTable built the row type with SubstraitTypeSystem.TYPE_FACTORY instead of the provider's type factory. - Column types came from col.dataType.deriveType(VALIDATOR), where VALIDATOR and EMPTY_CATALOG are static finals built on the global type factory and SqlConverterBase.CONNECTION_CONFIG. So a builder-configured typeFactory produced a catalog reader that used it while the tables inside were typed by the global one. Harmless today, since getCalciteConnectionConfig() returns the same case-insensitive config, but a custom type factory carrying a different type system was silently bypassed. Add createEmptyCatalog(ConverterProvider) and createValidator(ConverterProvider) helpers, build the validator once per call, and pass the provider's type factory and that validator into createSubstraitTable. EMPTY_CATALOG and VALIDATOR are retained and now defined via the same helpers against ConverterProvider.DEFAULT, so their values are unchanged. The validator is also built with the provider's SqlOperatorTable rather than a hardcoded SubstraitOperatorTable.INSTANCE, matching how the query path already sources its operator table. Identical for the default provider. CreateStatementParserProviderConfigTest covers both entry points; 3 of its 4 tests fail without this change.
bvolpato
reviewed
Aug 3, 2026
| assertSame( | ||
| fieldType, | ||
| typeFactory.canonizeType(fieldType), | ||
| "column types should be interned in the provider's type factory"); |
Member
There was a problem hiding this comment.
Nice targeted coverage around both entry points. Non-blocking test thought: Calcite uses a static interner here, so canonizing a field type cannot distinguish the provider factory from the global factory. Recording createSqlType calls on RecordingTypeFactory, or asserting a custom type-system result, would make this check protect the validator path too.
bvolpato
approved these changes
Aug 3, 2026
bvolpato
left a comment
Member
There was a problem hiding this comment.
LGTM! Clean provider-config propagation through CREATE parsing, with focused coverage for both entry points and defaults. Left one non-blocking test-strengthening note inline.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Finishes the deferred half of @vbarua's comment on #1035 —
"I wonder if it would make sense to get the RelTypeFactory and SqlConverterBase from the
ConverterProvider as well". #1036 threaded the provider into the
CalciteCatalogReaderconstruction; this covers the type derivation underneath it.
The gap
On the provider-injected path (
processCreateStatementsToCatalog(provider, …)→processCreateStatementsToSchema(provider, …)→createSubstraitTable(…)):createSubstraitTablebuilt the row type withSubstraitTypeSystem.TYPE_FACTORY, not theprovider's type factory.
col.dataType.deriveType(VALIDATOR), whereVALIDATORandEMPTY_CATALOGarestatic final, built on the global type factory plusSqlConverterBase.CONNECTION_CONFIG.So a builder-configured
typeFactoryproduced a catalog reader that used it while the tablesinside were typed by the global one. That is harmless today —
getCalciteConnectionConfig()returns the same case-insensitive config as
SqlConverterBase.CONNECTION_CONFIG— but a customtype factory carrying a different type system (different decimal precision limits, say) was
silently bypassed for table column types.
Changes
createEmptyCatalog(ConverterProvider)andcreateValidator(ConverterProvider)helpers. Because
SubstraitSqlValidatortakes its type factory from the catalog reader, fixingthe empty catalog fixes column derivation as well.
createSubstraitTable.EMPTY_CATALOGandVALIDATORare kept and now defined via the same helpers againstConverterProvider.DEFAULT, so their values are unchanged and nothing public was removed.Note on scope
Two things worth calling out explicitly, both easy to drop if you would rather they were separate:
converterProvider.getSqlOperatorTable()instead of ahardcoded
SubstraitOperatorTable.INSTANCE, matching how feat(isthmus)!: inject ConverterProvider into the SQL statement parsers #1035 made the query path source itsoperator table. Identical for the default provider; it only matters for a provider that adds
operators.
EMPTY_CATALOGandVALIDATORnow have no callers inside the class either (each entry pointderives its own from the provider). They are still
public, so they are retained — but if youwant them deprecated in favour of the provider-derived path, that is a one-line follow-up.
Independent of #1037 — no overlapping files, so the two can merge in either order.
🤖 Generated with AI