-
Notifications
You must be signed in to change notification settings - Fork 312
Description
What?
Support entities (tables and views) that have columns with unsupported data types.
Configuration
false(default) : Current behavior. Unsupported column types cause the entity to fail at startup.true: DAB silently drops unsupported columns from the schema and proceeds.
Behavior When true
| Concern | What Happens |
|---|---|
| Startup | Introspect all columns. Unsupported types are dropped from the internal model. Warning logged per column. |
| GraphQL / REST schema | Excluded columns don't exist. |
| SELECT | Excluded columns omitted from projection. Never fetched. |
| INSERT / UPDATE | Excluded columns omitted. DB default or NULL fills them. |
| fields.include | Excluded or unsupported columns are ignored. |
| fields.exclude | Excluded or unsupported columns are ignored. |
policy @item.field |
This is the one hard failure. Column reference causes startup exception. Policies are security boundaries, silent exclusion is not safe. |
| Client sends excluded column | 400 — field not recognized (same as any unknown field today). |
| Filter/OrderBy on excluded column | 400 — field not recognized. |
| NOT NULL, no default | Database will return standard error. Developer is responsible for defaults. |
Design Principles
| Principle | How |
|---|---|
| Transparent | Startup warnings list every dropped column and its native type. |
| Deterministic | Same schema + true = same columns dropped, every time. |
| Predictable | No coercion. No casting. No partial data. Columns are fully in or fully out. |
| Safe | Policies fail loud. DB errors surface honestly. DAB never touches data it can't represent. |
| Optional | false by default. Zero impact on existing users. |
Behavior When false (default, unchanged)
Unsupported column in entity fails to load with startup error. No regression, same as today.
Why?
Reduce blockers. Enable DAB adoption in real, messy databases, where "one unsupported column" is otherwise a dealbreaker. Teams can migrate services to DAB even if a few columns are currently unsupported. No need to wait for full support; just flip a switch.
Considerations
- What happens if an unsupported column is part of a primary key or foreign key? Fail to start.
- If a GraphQL relationship uses an excluded column as a join key? Fail to start.
- For entities backed by stored procedures? This feature does and can only apply to tables/views.
- Excluded columns don't appear in OpenAPI request/response schemas.
- When included in an entity Fields array? Fail to start.
- The proposal focuses on SQL databases only. JSON Schema constraint should enforce
mssql.
How?
How?
1. Config Model
Add exclude-unsupported-types to EntitySource:
[JsonPropertyName("exclude-unsupported-types")]
public bool ExcludeUnsupportedTypes { get; init; } = false;Update schemas/dab.draft.schema.json. Constrain to mssql only via JSON Schema.
2. Metadata Provider: Skip unsupported columns
The crash today is in SqlMetadataProvider.GetTableWithSchemaFromDataSetAsync() when DataReader.GetFieldType() returns null or the type is false in SupportedSqlDbTypes. When ExcludeUnsupportedTypes is true, log a warning and skip the column instead of throwing. The column never enters SourceDefinition.Columns.
if (columnTypeIsUnsupported)
{
if (entityConfig.Source.ExcludeUnsupportedTypes)
{
_logger.LogWarning(
"Entity '{EntityName}': column '{ColumnName}' of type '{NativeType}' "
+ "is unsupported and will be excluded.",
entityName, columnName, nativeTypeName);
continue;
}
throw new DataApiBuilderException(...);
}Because the column never enters the model, every downstream consumer (GraphQL schema builder, REST/OpenAPI, query builders, authorization) naturally ignores it. No column in the model means no field in the schema means no column in SQL projection. This is why a single toggle works.
Key files:
src/Core/Services/MetadataProviders/SqlMetadataProvider.cssrc/Core/Services/MetadataProviders/MsSqlMetadataProvider.cssrc/Core/Models/SqlTypeConstants.cs
3. Startup Validation: Hard failures
After metadata is populated and unsupported columns are excluded, validate that no excluded column is referenced where silent exclusion is unsafe. Fail to start if any of these are true:
| Condition | Behavior |
|---|---|
| Excluded column is part of a primary key | Startup exception |
| Excluded column is a foreign key or relationship join key | Startup exception |
Policy @item.field references an excluded column |
Startup exception |
fields.include or fields.exclude explicitly names an excluded column |
Startup exception |
| Entity source type is stored procedure | Startup exception (feature applies to tables/views only) |
| Excluded column is NOT NULL with no default | Log warning (not a failure, DB will error on INSERT) |
Policy validation reuses the existing @item.* extraction pattern from AuthorizationResolver.cs. Add these checks to RuntimeConfigValidator.cs.
4. Fields.include / Fields.exclude
When the excluded column is NOT explicitly listed in fields.include or fields.exclude, it is silently ignored since it never enters SourceDefinition.Columns. No code change needed for this path.
When the excluded column IS explicitly listed, fail at startup per the table above.
5. CLI
Add --exclude-unsupported-types to dab add and dab update in src/Cli/. Wire to the config serializer.
dab add SpatialData --source dbo.SpatialData --exclude-unsupported-types true6. Tests
Add a column with type xml (already false in SupportedSqlDbTypes) to an existing MSSQL test table. Use TestCategory=MsSql.
| Test | Validates |
|---|---|
Startup succeeds with flag true |
Entity loads, column absent from SourceDefinition.Columns |
Startup fails with flag false |
Current behavior preserved |
| GraphQL schema excludes column | Introspection shows no field |
| REST GET omits column | JSON response has no key |
| REST POST with excluded column returns 400 | Field not recognized |
| Filter on excluded column returns 400 | Field not recognized |
| Policy referencing excluded column fails startup | DataApiBuilderException thrown |
fields.include naming excluded column fails startup |
DataApiBuilderException thrown |
| Excluded column in primary key fails startup | DataApiBuilderException thrown |
| INSERT without excluded NOT NULL column surfaces DB error | DAB passes through the database error |
| Excluded column NOT NULL with no default logs warning | Warning logged at startup |
| Flag on stored procedure entity fails startup | Feature only applies to tables/views |
{ "entities": { "SpatialData": { "source": "dbo.SpatialData", "exclude-unsupported-types": true // new! } } }