While answering a question on the ODCS spec repo about declaring more than one date format (bitol-io/open-data-contract-standard#306), I traced how logicalTypeOptions.format flows through the CLI and ended up somewhere I didn't expect. Filing it as a question rather than a bug, because the answer may well be "intentional".
A declared date format is never applied
For a property with logicalType: date / timestamp / time, logicalTypeOptions.format holds a JDK DateTimeFormatter pattern (yyyy-MM-dd, per the ODCS schema's own examples). As far as I can tell it is never read:
engines/checks/create_checks.py builds checks from minLength, maxLength, minimum, maximum, exclusiveMinimum, exclusiveMaximum, pattern and enum. format is not among them.
export/jsonschema_exporter.py does read it, but convert_type_format substitutes a fixed value for these types and drops the declared one:
if type_str.lower() in ["timestamp", "timestamp_tz", "date-time", "datetime"]:
return "string", "date-time"
if type_str.lower() in ["date"]:
return "string", "date"
if type_str.lower() in ["time"]:
return "string", "time"
So format: "dd/MM/yyyy" on a date column has no effect on any server type.
That may be the right call — a JDK pattern has no JSON Schema equivalent, and date-time is the closest thing available. If so, it's worth saying in the docs, because the option looks enforceable and isn't.
It behaves differently on a string property
For logicalType: string, convert_type_format passes the declared format straight through to JSON Schema, where fastjsonschema validates it. But check_jsonschema returns early unless server.format == "json", so:
| property |
server.format: json |
any other server |
string with format |
validated |
ignored |
date/timestamp/time with format |
ignored (overridden) |
ignored |
Same contract option, three different fates depending on the logical type and the server. That's the part that seems most worth resolving one way or the other.
Other options with no reader
While looking, these appear in the ODCS 3.1.0 logicalTypeOptions surface but have no handling in export/ or engines/:
multipleOf (integer, number) — written by the Excel importer, read by nothing
maxItems, minItems, uniqueItems (array)
maxProperties, minProperties (object)
defaultTimezone (timestamp)
The array and object families look like the most substantive gap, since minItems/uniqueItems are checks a warehouse could genuinely run.
Question
Is the intent that logicalTypeOptions is descriptive metadata, with only the subset above enforced deliberately — or should the check builder be growing to cover more of it?
Happy to send a PR either way: docs clarifying which options are enforced and where, or an implementation of whichever of these you'd want checked. I'd rather ask first than guess at the scope.
While answering a question on the ODCS spec repo about declaring more than one date format (bitol-io/open-data-contract-standard#306), I traced how
logicalTypeOptions.formatflows through the CLI and ended up somewhere I didn't expect. Filing it as a question rather than a bug, because the answer may well be "intentional".A declared date format is never applied
For a property with
logicalType: date/timestamp/time,logicalTypeOptions.formatholds a JDKDateTimeFormatterpattern (yyyy-MM-dd, per the ODCS schema's own examples). As far as I can tell it is never read:engines/checks/create_checks.pybuilds checks fromminLength,maxLength,minimum,maximum,exclusiveMinimum,exclusiveMaximum,patternandenum.formatis not among them.export/jsonschema_exporter.pydoes read it, butconvert_type_formatsubstitutes a fixed value for these types and drops the declared one:So
format: "dd/MM/yyyy"on a date column has no effect on any server type.That may be the right call — a JDK pattern has no JSON Schema equivalent, and
date-timeis the closest thing available. If so, it's worth saying in the docs, because the option looks enforceable and isn't.It behaves differently on a string property
For
logicalType: string,convert_type_formatpasses the declared format straight through to JSON Schema, wherefastjsonschemavalidates it. Butcheck_jsonschemareturns early unlessserver.format == "json", so:server.format: jsonstringwithformatdate/timestamp/timewithformatSame contract option, three different fates depending on the logical type and the server. That's the part that seems most worth resolving one way or the other.
Other options with no reader
While looking, these appear in the ODCS 3.1.0
logicalTypeOptionssurface but have no handling inexport/orengines/:multipleOf(integer, number) — written by the Excel importer, read by nothingmaxItems,minItems,uniqueItems(array)maxProperties,minProperties(object)defaultTimezone(timestamp)The array and object families look like the most substantive gap, since
minItems/uniqueItemsare checks a warehouse could genuinely run.Question
Is the intent that
logicalTypeOptionsis descriptive metadata, with only the subset above enforced deliberately — or should the check builder be growing to cover more of it?Happy to send a PR either way: docs clarifying which options are enforced and where, or an implementation of whichever of these you'd want checked. I'd rather ask first than guess at the scope.