-
Notifications
You must be signed in to change notification settings - Fork 4
Initial spec for lists and structs #113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
76910f8
7733b40
1066f66
69410b7
614dccd
ee80c62
049b441
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -136,6 +136,8 @@ The supported types are: | |
| * `date`: calendar dates, written as ISO 8601 strings (`YYYY-MM-DD`, e.g. `2024-01-31`). | ||
| * `datetime`: date-times, written as ISO 8601 strings. Without a `time_zone` they carry an offset (e.g. `2024-01-31T09:30:00Z`); with a `time_zone` they're written zoneless and interpreted in that zone (see [Time zones](#time-zones)). | ||
| * `enum`: a column with repeated values from a known set. The allowed values are listed in the `values` property. | ||
| * `list(element_type)`: an ordered sequence of zero or more elements of the given type (see [List element types](#list-element-types)). | ||
| * `struct`: a structured record with named fields documented in the required `fields` property (see [Struct fields](#struct-fields)). | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you thinking of using these for very nested data? I personally haven't encountered these "in the wild". What would be the advantage of a
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not a data structure that I'd generally recommend, since I would prefer a relation framing with multiple tables, but it is something that you get in parquet files so its important that we can represent it. |
||
|
|
||
| #### Measures | ||
|
|
||
|
|
@@ -156,9 +158,63 @@ A `number(quantity)` column can also declare its `units`: a free-text string nam | |
| range: [0, 5000] | ||
| ``` | ||
|
|
||
| #### List element types | ||
|
|
||
| The element type in `list(element_type)` may be any type: `string`, `number`, `number(id)`, `number(ordinal)`, `number(quantity)`, `boolean`, `date`, `datetime`, `enum`, or `struct`. The same properties that apply to a column of that type apply when it is used as a list element type — `values` for `enum`, `fields` for `struct`, and so on. | ||
|
|
||
| ```yaml | ||
| - name: tags | ||
| type: list(string) | ||
| examples: [nature, outdoor, urban, photography, wildlife] | ||
|
Comment on lines
+166
to
+167
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment below about the enum. How would this be different? |
||
|
|
||
| - name: categories | ||
| type: list(enum) | ||
| values: [food, drink, dessert] | ||
|
Comment on lines
+170
to
+171
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks the same as an enum. What's different here?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a multiselect — an |
||
|
|
||
| - name: line_items | ||
| type: list(struct) | ||
| fields: | ||
| - name: product_id | ||
| type: number(id) | ||
| examples: [101, 204, 389] | ||
| - name: quantity | ||
| type: number(quantity) | ||
| units: units | ||
| range: [1, 100] | ||
| - name: price | ||
| type: number(quantity) | ||
| units: USD | ||
| range: [0.99, 999.99] | ||
| ``` | ||
|
|
||
| #### Struct fields | ||
|
|
||
| A `struct` column may include a `fields` property — an ordered list of field descriptors. Each field descriptor uses the same schema as a column descriptor, with two differences: | ||
|
|
||
| * `primary_key` and `foreign_key` constraints are not meaningful on struct fields and are not permitted. | ||
| * A field may itself be `list(...)` or `struct` (with its own `fields`), allowing deep nesting. | ||
|
|
||
| ```yaml | ||
| - name: address | ||
| type: struct | ||
| fields: | ||
| - name: street | ||
| type: string | ||
| examples: [123 Main St, 456 Oak Ave, 789 Elm Dr] | ||
| - name: city | ||
| type: string | ||
| examples: [Portland, Austin, Chicago] | ||
| - name: zip | ||
| type: string | ||
| examples: ["97201", "78701", "60601"] | ||
| - name: country | ||
| type: enum | ||
| values: [US, CA, MX] | ||
|
Comment on lines
+194
to
+208
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a hard time seeing the difference here with the |
||
| ``` | ||
|
|
||
| #### Representative values | ||
|
|
||
| Every type has some way of representing the data it contains: an exhaustive set of values, a range, or a handful of examples. Each such column carries exactly one of the following three properties, determined by the column's `type`: | ||
| Most typed columns carry exactly one of the following three properties to represent the data they contain. The exceptions are `boolean` (values are always `true`/`false`) and `struct` (whose fields carry their own). | ||
|
|
||
| * `values`: the allowed values for an `enum` column. Can be a list (`[M, F, U]`) when values are self-explanatory, or a map (`{M: Male, F: Female, U: Unknown}`) when values need labels. The values themselves must be scalars (string, number, or boolean); in the map form the labels must be strings. (`boolean` columns implicitly have `values: [true, false]`, no need to explicitly include it.) | ||
| * `range`: a two-element list `[min, max]` giving the inclusive minimum and maximum *observed* in the column. Like `examples`, it describes the data rather than constraining it — a value outside the range will generate a warning, not a validation error. Used for the ordered numeric and temporal types: `number(ordinal)`, `number(quantity)`, `date`, and `datetime`. Both elements must match the column's type, and the minimum must not exceed the maximum. | ||
|
|
@@ -168,6 +224,8 @@ Every type has some way of representing the data it contains: an exhaustive set | |
|
|
||
| `boolean` columns are the exception to this rule because they can only contain `true`, `false`, and (if not required) `null`. | ||
|
|
||
| For `list(element_type)` columns, the same three properties apply but describe the element values, not the lists themselves. Use `values` for `list(enum)`, `range` for `list(number(ordinal))`, `list(number(quantity))`, `list(date)`, and `list(datetime)`, and `examples` for all other list types. Each property means the same thing it would for a scalar column of the element type — for instance, `range` on a `list(number(quantity))` column gives the minimum and maximum element value observed across all lists. | ||
|
|
||
| #### Time zones | ||
|
|
||
| A `datetime` column can declare its `time_zone`, which says how to interpret its values as moments in time. The value is either an [IANA time zone name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) or the sentinel `naive`: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are list and struct the right names?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
list definitely. struct is as good as any imo