Derive a column's datatype in columnDatatype alone
This commit is contained in:
+17
-30
@@ -82,8 +82,14 @@ func checkColumns(s nodeScope) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err := columnDatatype(column); err != nil {
|
if len(items) == 0 {
|
||||||
return fmt.Errorf("%s: field %q: %w", path, name, err)
|
return nil
|
||||||
|
}
|
||||||
|
first := itemDatatype(items[0])
|
||||||
|
for _, it := range items[1:] {
|
||||||
|
if d := itemDatatype(it); d != first {
|
||||||
|
return fmt.Errorf("%s: field %q: %w", path, name, disagreement(items[0], first, it, d))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -101,41 +107,22 @@ func checkColumns(s nodeScope) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// columnDatatype is the datatype a column's items hold. They must agree, since a
|
// columnDatatype is the datatype a column holds, which its first item decides: checkColumns refuses
|
||||||
// column holds one; a column only ever null is a string.
|
// a column whose items disagree. A table's column, like one only ever null, has no item and is a string.
|
||||||
func columnDatatype(n node) (DataType, error) {
|
func columnDatatype(n node) DataType {
|
||||||
items, _ := columnItems(n)
|
items, _ := columnItems(n)
|
||||||
if len(items) == 0 {
|
if len(items) == 0 {
|
||||||
return DataTypeString, nil
|
return DataTypeString
|
||||||
}
|
}
|
||||||
first := itemDatatype(items[0])
|
return itemDatatype(items[0])
|
||||||
for _, t := range items[1:] {
|
|
||||||
if d := itemDatatype(t); d != first {
|
|
||||||
return first, disagreement(items[0], first, t, d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return first, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// itemDatatype is the datatype a column item declares, else that of the column it is.
|
// itemDatatype is the datatype a column item declares, else that of the column it reads.
|
||||||
func itemDatatype(t *template) DataType {
|
func itemDatatype(t *template) DataType {
|
||||||
if t.datatype != DataTypeString {
|
if t.datatype == DataTypeString && t.readsColumn != nil {
|
||||||
|
return columnDatatype(t.readsColumn.column)
|
||||||
|
}
|
||||||
return t.datatype
|
return t.datatype
|
||||||
}
|
|
||||||
return readDatatype(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
// readDatatype is the datatype of the column t is, reading it by one reference alone; a string
|
|
||||||
// when t reads none.
|
|
||||||
func readDatatype(t *template) DataType {
|
|
||||||
if t.readsColumn == nil {
|
|
||||||
return DataTypeString
|
|
||||||
}
|
|
||||||
items, _ := columnItems(t.readsColumn.column)
|
|
||||||
if len(items) == 0 {
|
|
||||||
return DataTypeString
|
|
||||||
}
|
|
||||||
return itemDatatype(items[0]) // checkColumns refuses that column where its items disagree
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// columnItems is a column's template items, its choices unwrapped, and whether one is null.
|
// columnItems is a column's template items, its choices unwrapped, and whether one is null.
|
||||||
|
|||||||
@@ -254,8 +254,7 @@ func recordOf(n node) (*template, []Column, error) {
|
|||||||
}
|
}
|
||||||
columns := make([]Column, len(names))
|
columns := make([]Column, len(names))
|
||||||
for i, name := range names {
|
for i, name := range names {
|
||||||
datatype, _ := columnDatatype(t.fields[name]) // checkColumns refused items that disagree wherever DataType is read
|
columns[i] = Column{Name: name, DataType: columnDatatype(t.fields[name])}
|
||||||
columns[i] = Column{Name: name, DataType: datatype}
|
|
||||||
}
|
}
|
||||||
return t, columns, nil
|
return t, columns, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ Self-sufficiency 5.6), every seat capped by Locality, and all nine naming
|
|||||||
|
|
||||||
This round, in order:
|
This round, in order:
|
||||||
|
|
||||||
- Derive a column's datatype in one place: `columnItems` yields nothing for a
|
|
||||||
`tableColumn`, and six callers re-derive it from items.
|
|
||||||
- Give `head`, `index`, `bound` and `draw` one meaning each, name `table.family`
|
- Give `head`, `index`, `bound` and `draw` one meaning each, name `table.family`
|
||||||
for the root it returns, and replace the token kind bytes `'l'`, `'t'`, `'f'` and
|
for the root it returns, and replace the token kind bytes `'l'`, `'t'`, `'f'` and
|
||||||
`'b'`, whose `'l'` means different things in `ftoken` and `formatToken`.
|
`'b'`, whose `'l'` means different things in `ftoken` and `formatToken`.
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ func (p *valueProof) checkDatatype(path string, n node) error {
|
|||||||
if !ok || t.datatype == DataTypeString {
|
if !ok || t.datatype == DataTypeString {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if d := readDatatype(t); d == t.datatype {
|
if r := t.readsColumn; r != nil && columnDatatype(r.column) == t.datatype {
|
||||||
return fmt.Errorf(`%s: %s takes datatype %s from the column it reads; drop "datatype"`, path, t.format, d)
|
return fmt.Errorf(`%s: %s takes datatype %s from the column it reads; drop "datatype"`, path, t.format, t.datatype)
|
||||||
}
|
}
|
||||||
if reason := p.proveColumnItem(t).not[t.datatype]; reason != "" {
|
if reason := p.proveColumnItem(t).not[t.datatype]; reason != "" {
|
||||||
return fmt.Errorf("%s: datatype %s: %s", path, t.datatype, reason)
|
return fmt.Errorf("%s: datatype %s: %s", path, t.datatype, reason)
|
||||||
|
|||||||
Reference in New Issue
Block a user