Add opt-in domain-based CLR type mapping (boolean/guid)#1267
Open
sencagri wants to merge 1 commit intoFirebirdSQL:masterfrom
Open
Add opt-in domain-based CLR type mapping (boolean/guid)#1267sencagri wants to merge 1 commit intoFirebirdSQL:masterfrom
sencagri wants to merge 1 commit intoFirebirdSQL:masterfrom
Conversation
Closes FirebirdSQL#1266 (proposal). Restores IBProvider-style behaviour for codebases that store booleans as SMALLINT and guids as CHAR(16) OCTETS behind named domains. Connection string keys (both default to empty - feature is fully off when unset; no extra catalog query, no DbField allocation change): boolean domains = D_BOOL%,IS\_% guid domains = D_GUID% Patterns use SQL LIKE syntax. Matching is case-insensitive against RDB$FIELD_SOURCE; system domains (RDB$*) are never matched. Design * RawDbDataType vs DbDataType. DbField gains RawDbDataType (the actual SQL/wire type, computed from sqltype/subtype/length/charset as before) and OverrideDataType (CLR-level reporting only). DbDataType returns the override when set, otherwise RawDbDataType. All wire serialisation paths (GdsStatement.WriteRawParameter / ReadRawValue, XsqldaMarshaler, DbValue.GetBytes, DbField.FixNull) explicitly use RawDbDataType so the override cannot leak into the protocol layer. * DomainNameResolver. Per-FbConnectionInternal cache of (relation, field) -> domain name. Populated lazily on Prepare via a single SELECT on RDB\$RELATION_FIELDS (one round-trip per batch of unseen columns). Guarded by an _isResolving flag so its own internal query cannot recurse. Negative entries are cached so a missing or failed lookup does not retry every prepare. Fetch failures are swallowed (best-effort): an opt-in feature must never break user's normal queries. * Parameter binding. FbCommand.NormalizeDomainParameterValue converts bool inputs to the underlying numeric wire type (SmallInt/Integer/ BigInt/Numeric/Decimal) using RawDbDataType, so callers can pass true or false to a SMALLINT-backed boolean column directly. Guid handling reuses the provider's existing CHAR(16) OCTETS <-> Guid path. * DbValue.GetBoolean. Tightened from Convert.ToBoolean to explicit short/int/long/decimal -> bool with a fallback, so reading a SMALLINT with a Boolean override is safe and culture-independent. Opt-out path When neither connection-string key is set, ConnectionString.HasDomainTypeMappings is false and FbCommand.Prepare returns before touching the resolver. RDB\$RELATION_FIELDS is never queried, no per-field state changes, behaviour is identical to master. Tests * DomainPatternListTests - 12 unit tests for LIKE pattern parsing (escape handling, case-insensitivity, RDB\$ exclusion, edge cases). * DomainTypeMappingTests - 12 integration tests covering schema-level reporting, parameter round-trip (bool -> SMALLINT -> bool), guid round-trip, NULL handling, non-matching patterns staying as raw types, DataAdapter round-trip, GetSchemaTable, and resolver caching / re-entry. * ConnectionStringTests - parsing and builder coverage for the two new keys. Compatibility No breaking changes. Public API surface adds two properties on FbConnectionStringBuilder (BooleanDomains, GuidDomains) and is backward-compatible at the wire level.
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.
PR review for #1266 (proposal). Restores IBProvider-style behaviour for codebases that store booleans as SMALLINT and guids as CHAR(16) OCTETS behind named domains.
Connection string keys (both default to empty - feature is fully off when unset; no extra catalog query, no DbField allocation change):
boolean domains = D_BOOL%,IS_%
guid domains = D_GUID%
Patterns use SQL LIKE syntax. Matching is case-insensitive against RDB$FIELD_SOURCE; system domains (RDB$*) are never matched.
Design
RawDbDataType vs DbDataType. DbField gains RawDbDataType (the actual SQL/wire type, computed from sqltype/subtype/length/charset as before) and OverrideDataType (CLR-level reporting only). DbDataType returns the override when set, otherwise RawDbDataType. All wire serialisation paths (GdsStatement.WriteRawParameter / ReadRawValue, XsqldaMarshaler, DbValue.GetBytes, DbField.FixNull) explicitly use RawDbDataType so the override cannot leak into the protocol layer.
DomainNameResolver. Per-FbConnectionInternal cache of (relation, field) -> domain name. Populated lazily on Prepare via a single SELECT on RDB$RELATION_FIELDS (one round-trip per batch of unseen columns). Guarded by an _isResolving flag so its own internal query cannot recurse. Negative entries are cached so a missing or failed lookup does not retry every prepare. Fetch failures are swallowed (best-effort): an opt-in feature must never break user's normal queries.
Parameter binding. FbCommand.NormalizeDomainParameterValue converts bool inputs to the underlying numeric wire type (SmallInt/Integer/ BigInt/Numeric/Decimal) using RawDbDataType, so callers can pass true or false to a SMALLINT-backed boolean column directly. Guid handling reuses the provider's existing CHAR(16) OCTETS <-> Guid path.
DbValue.GetBoolean. Tightened from Convert.ToBoolean to explicit short/int/long/decimal -> bool with a fallback, so reading a SMALLINT with a Boolean override is safe and culture-independent.
Opt-out path
When neither connection-string key is set,
ConnectionString.HasDomainTypeMappings is false and FbCommand.Prepare returns before touching the resolver. RDB$RELATION_FIELDS is never queried, no per-field state changes, behaviour is identical to master.
Tests
Compatibility
No breaking changes. Public API surface adds two properties on FbConnectionStringBuilder (BooleanDomains, GuidDomains) and is backward-compatible at the wire level.