Skip to content

Commit

Permalink
thema: Remove native CUE lens sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
sam boyer committed Jun 12, 2023
1 parent fd8b835 commit a2e44f9
Show file tree
Hide file tree
Showing 16 changed files with 49 additions and 61 deletions.
27 changes: 7 additions & 20 deletions lineage.cue
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ import (
// Thus, for a lineage with schema versions [0,0], [0,1], [1,0], [2,0], [2,1],
// the following lenses must exist (implicit lenses are wrapped in parentheses):
//
// ([0,0] -> [0,1])
// [0,1] -> [0,0]
// [0,1] -> [1,0]
// ([0,0] -> [0,1])
// [1,0] -> [0,1]
// [1,0] -> [2,0]
// [0,1] -> [1,0]
// [2,0] -> [1,0]
// ([2,0] -> [2,1])
// [1,0] -> [2,0]
// [2,1] -> [2,0]
// ([2,0] -> [2,1])
//
// To be valid, a lineage must define the exact set of explicit lenses entailed by its
// set of schema versions. It is not permitted to explicitly define a lens across
Expand All @@ -79,7 +79,7 @@ import (
// list. Thema tooling that modifies and emits lineages definitions may produce lenses
// sorted in ascending order, rather than original source order.
// TODO switch to descending order - newest on top is nicer to read
lenses: [...#Lens]
SL=lenses: [...#Lens]

_atLeastOneSchema: len(schemas) > 0

Expand All @@ -92,21 +92,8 @@ import (
_schemas: [#SchemaDef & {version: [0, 0]}]
}

// SS=_sortedSchemas: list.Sort(_schemas, {
// x: #SchemaDef
// y: #SchemaDef
// less: (_cmpSV & {l: x.version, r: y.version}).out == -1
// }) & list.MinItems(1)

// TODO add informative validation that exactly the expected set of explicit lenses exist
_sortedLenses: list.Sort(lenses, {
x: #Lens
y: #Lens
less: ((_cmpSV & {l: x.to, r: y.to}).out == -1 || (x.to == y.to && x.from[0] < y.from[0]))
})

_forwardLenses: [ for lens in _sortedLenses if {lens.to[0] > lens.from[0]} {lens}]
_backwardLenses: [ for lens in _sortedLenses if {lens.to[0] <= lens.from[0]} {lens}]
_forwardLenses: [ for lens in SL if {lens.to[0] > lens.from[0]} {lens}]
_backwardLenses: [ for lens in SL if {lens.to[0] <= lens.from[0]} {lens}]

// preserved for debugging
// lensVersions: {
Expand Down
4 changes: 3 additions & 1 deletion lineage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ func TestBindLineage(t *testing.T) {
fmt.Fprintf(tc, "Schema count: %v\n", slen)
fmt.Fprintf(tc, "Schema versions: %s\n", lin.allVersions())

slpath := cue.MakePath(cue.Hid("_sortedLenses", "github.com/grafana/thema"))
// lenseselem := cue.Hid("_sortedLenses", "github.com/grafana/thema")
lenseselem := cue.Str("lenses")
slpath := cue.MakePath(lenseselem)
llen, err := lin.Underlying().LookupPath(slpath).Len().Int64()
if err != nil {
tc.Fatal("error getting schemas len", err)
Expand Down
4 changes: 0 additions & 4 deletions testdata/invalidlineage/empty-schemas.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,3 @@ name: "empty-schemas"
schemas: []
-- out/bindfail --
incompatible list lengths (0 and 1)
_sortedSchemas: invalid value [] (does not satisfy list.MinItems(1)): len(list) < MinItems(1) (0 < 1):
../../lineage.cue:98:7
../../lineage.cue:94:21
../../lineage.cue:98:21
8 changes: 4 additions & 4 deletions testdata/invalidlineage/second-schema-versionless.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ lenses: [
]
-- out/bindfail --
_schemasAreOrdered.1: conflicting values true and false:
../../lineage.cue:125:3
../../lineage.cue:126:4
../../lineage.cue:131:5
../../lineage.cue:132:11
../../lineage.cue:126:3
../../lineage.cue:127:4
../../lineage.cue:132:5
../../lineage.cue:133:11
./in.cue:4:1
2 changes: 1 addition & 1 deletion testdata/isappendonly/invalid/boundaries.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ lin2: schemas: [{
}]
-- out/isappendonly-fail --
field anInt not present in {anInt:*12 | >0 & <=24 & int}:
../../../lineage.cue:247:10
../../../lineage.cue:248:10
./in.cue:7:10
missing field "anInt"
2 changes: 1 addition & 1 deletion testdata/isappendonly/invalid/default.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ lin2: schemas: [{
}]
-- out/isappendonly-fail --
field aunion not present in {aunion:*"bar" | "foo" | "baz"}:
../../../lineage.cue:247:10
../../../lineage.cue:248:10
./in.cue:16:13
missing field "aunion"
2 changes: 1 addition & 1 deletion testdata/isappendonly/invalid/embedref.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ lin2: schemas: [{
}]
-- out/isappendonly-fail --
field #EmbedRef not present in {#EmbedRef:{refField1:string,refField2:1},refField1:string,refField2:1}:
../../../lineage.cue:247:10
../../../lineage.cue:248:10
./in.cue:21:13
field refField2 not present in {refField1:string,refField2:1}:
./in.cue:24:20
Expand Down
7 changes: 4 additions & 3 deletions testdata/isappendonly/invalid/nested.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ lin2: schemas: [{
}
}]
-- out/isappendonly-fail --
field aNewOptionalField not present in {aField:string}:
./in.cue:8:13
field anObject not present in {anObject:{aField:string}}:
../../../lineage.cue:247:10
./in.cue:18:13
field not allowed in closed struct: aNewOptionalField
../../../lineage.cue:248:10
./in.cue:7:10
missing field "anObject"
2 changes: 1 addition & 1 deletion testdata/isappendonly/invalid/newfield.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ lin2: schemas: [{
}
}]
-- out/isappendonly-fail --
field not allowed in closed struct: secondfield
required field is optional in subsumed value: secondfield
value not an instance
2 changes: 1 addition & 1 deletion testdata/isappendonly/invalid/noref.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ lin2: schemas: [{
}]
-- out/isappendonly-fail --
field #Baz not present in {someField:string,#Baz:{run:string,tell:bytes}}:
../../../lineage.cue:247:10
../../../lineage.cue:248:10
./in.cue:22:13
missing field "#Baz"
required field is optional in subsumed value: dat
6 changes: 4 additions & 2 deletions testdata/isappendonly/invalid/optional.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@ lin2: schemas: [{
}
}]
-- out/isappendonly-fail --
field not allowed in closed struct: aNewOptionalField
value not an instance
field aNewOptionalField not present in {aField:string}:
../../../lineage.cue:248:10
./in.cue:7:10
missing field "aNewOptionalField"
2 changes: 1 addition & 1 deletion testdata/isappendonly/invalid/refstruct.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ lin2: schemas: [{
}]
-- out/isappendonly-fail --
field aBaz not present in {aBaz:{run:string,dat:>=-2147483648 & <=2147483647 & int},#Baz:{run:string,dat:>=-2147483648 & <=2147483647 & int}}:
../../../lineage.cue:247:10
../../../lineage.cue:248:10
./in.cue:22:13
missing field "aBaz"
required field is optional in subsumed value: tell
2 changes: 1 addition & 1 deletion testdata/isappendonly/invalid/stringconstraint.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ lin2: schemas: [{
}]
-- out/isappendonly-fail --
field aString not present in {aString:strings.MinRunes(2),anObject:{aField:int}}:
../../../lineage.cue:247:10
../../../lineage.cue:248:10
./in.cue:25:10
missing field "aString"
invalid value strings.MinRunes(2) (does not satisfy strings.MinRunes(1)): error in call to strings.MinRunes: non-concrete value string:
Expand Down
32 changes: 16 additions & 16 deletions testdata/lineage/basic-multiversion.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,11 @@ schemas: [{
}]

lenses: [{
to: [0, 3]
from: [1, 0]
to: [0, 0]
from: [0, 1]
input: _
result: {
init: input.renamed
if (input.optional != _|_) {
optional: input.optional
}

withDefault: input.withDefault
init: input.init
}
},
{
Expand All @@ -174,6 +169,19 @@ lenses: [{
withDefault: "foo"
}
},
{
to: [0, 3]
from: [1, 0]
input: _
result: {
init: input.renamed
if (input.optional != _|_) {
optional: input.optional
}

withDefault: input.withDefault
}
},
{
to: [1, 0]
from: [0, 3]
Expand All @@ -200,14 +208,6 @@ lenses: [{
withDefault: "foo"
}
},
{
to: [0, 0]
from: [0, 1]
input: _
result: {
init: input.init
}
},
{
to: [1, 1]
from: [2, 0]
Expand Down
6 changes: 3 additions & 3 deletions translate.cue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import "list"
//
// TODO functionize
#Translate: {
L=lin: #Lineage
L=lin: _
I=inst: {...}
FV=from: #SyntacticVersion
TV=to: #SyntacticVersion
Expand Down Expand Up @@ -55,7 +55,7 @@ import "list"
let prior = _accum[i]

// the actual schema def
let schdef = L._sortedSchemas[pos]
let schdef = L.schemas[pos]

// TODO does having this field in the result, even hidden, cause a problem? does using an alias cause the computation to run more than once?
_lens: L._backwardLenses[(L._flatidx & {v: schdef.version}).out] & {
Expand Down Expand Up @@ -84,7 +84,7 @@ import "list"
// translation, inclusive of the starting schema.
let lo = (L._flatidx & {v: FV}).out
let hi = (L._flatidx & {v: TV}).out
let schrange = list.Slice(L._sortedSchemas, lo+1, hi+1)
let schrange = list.Slice(L.schemas, lo+1, hi+1)

_accum: [{result: I, to: FV}, for i, schdef in schrange {
// alias pointing to the previous item in the list we're building
Expand Down
2 changes: 1 addition & 1 deletion traverse.cue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ package thema
inst: {...} // TODO consistently rename to 'object' or something

out: #SyntacticVersion
out: [ for _, sch in lin._sortedSchemas if ((sch._#schema & inst) != _|_) {sch.version}][0]
out: [ for _, sch in lin.schemas if ((sch._#schema & inst) != _|_) {sch.version}][0]
}

// #LinkedInstance represents data that is an instance of some schema, the
Expand Down

0 comments on commit a2e44f9

Please sign in to comment.