snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
370
server/pkg/dal/alteration.go
Normal file
370
server/pkg/dal/alteration.go
Normal file
@@ -0,0 +1,370 @@
|
||||
package dal
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type (
|
||||
Alteration struct {
|
||||
ID uint64
|
||||
BatchID uint64
|
||||
DependsOn uint64
|
||||
Resource string
|
||||
ResourceType string
|
||||
ConnectionID uint64
|
||||
|
||||
AttributeAdd *AttributeAdd
|
||||
AttributeDelete *AttributeDelete
|
||||
AttributeReType *AttributeReType
|
||||
AttributeReEncode *AttributeReEncode
|
||||
ModelAdd *ModelAdd
|
||||
ModelDelete *ModelDelete
|
||||
}
|
||||
|
||||
AlterationSet []*Alteration
|
||||
|
||||
AttributeAdd struct {
|
||||
Attr *Attribute `json:"attr"`
|
||||
}
|
||||
|
||||
AttributeDelete struct {
|
||||
Attr *Attribute `json:"attr"`
|
||||
}
|
||||
|
||||
AttributeReType struct {
|
||||
Attr *Attribute `json:"attr"`
|
||||
To Type `json:"to"`
|
||||
}
|
||||
|
||||
AttributeReEncode struct {
|
||||
Attr *Attribute `json:"attr"`
|
||||
To Codec `json:"to"`
|
||||
}
|
||||
|
||||
ModelAdd struct {
|
||||
Model *Model `json:"model"`
|
||||
}
|
||||
|
||||
ModelDelete struct {
|
||||
Model *Model `json:"model"`
|
||||
}
|
||||
|
||||
// auxAttributeType is a helper struct used for marshaling/unmarshaling
|
||||
//
|
||||
// This is required since the Type inside the Attribute is an interface and we
|
||||
// need to help the encoding/json a bit.
|
||||
auxAttributeReType struct {
|
||||
Attr *Attribute `json:"attr"`
|
||||
To *auxAttributeType `json:"to"`
|
||||
}
|
||||
|
||||
// auxAttributeReEncode is a helper struct used for marshaling/unmarshaling
|
||||
//
|
||||
// This is required since the Codec inside the Attribute is an interface and we
|
||||
// need to help the encoding/json a bit.
|
||||
auxAttributeReEncode struct {
|
||||
Attr *Attribute `json:"attr"`
|
||||
To *auxStoreCodec `json:"to"`
|
||||
}
|
||||
)
|
||||
|
||||
// Merge merges the two alteration slices
|
||||
func (aa AlterationSet) Merge(bb AlterationSet) (cc AlterationSet) {
|
||||
// @todo the Merge function currently just merges the two slices together
|
||||
// and removes any duplicates that would occur due to the merge.
|
||||
// We should also handle overlapping/transitive alterations to reduce
|
||||
// the amount of needles processing.
|
||||
//
|
||||
// A quick list of overlapping alterations:
|
||||
// * attribute A added and then renamed from A to A'
|
||||
// * attribute A renamed to A' and then renamed to A''
|
||||
// * attribute A deleted and then created
|
||||
|
||||
aux := append(aa, bb...)
|
||||
seen := make(map[int]bool, len(aux)/2)
|
||||
|
||||
for i, a := range aux {
|
||||
if seen[i] {
|
||||
continue
|
||||
}
|
||||
|
||||
found := false
|
||||
for j := i + 1; j < len(aux); j++ {
|
||||
if seen[j] {
|
||||
continue
|
||||
}
|
||||
|
||||
if a.compare(*aux[j]) {
|
||||
if !found {
|
||||
cc = append(cc, aux[j])
|
||||
}
|
||||
|
||||
seen[j] = true
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
cc = append(cc, a)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (a AttributeReType) MarshalJSON() ([]byte, error) {
|
||||
aux := auxAttributeReType{
|
||||
Attr: a.Attr,
|
||||
To: &auxAttributeType{},
|
||||
}
|
||||
|
||||
switch t := a.To.(type) {
|
||||
case *TypeID:
|
||||
aux.To.Type = "ID"
|
||||
aux.To.ID = t
|
||||
|
||||
case *TypeRef:
|
||||
aux.To.Type = "Ref"
|
||||
aux.To.Ref = t
|
||||
|
||||
case *TypeTimestamp:
|
||||
aux.To.Type = "Timestamp"
|
||||
aux.To.Timestamp = t
|
||||
|
||||
case *TypeTime:
|
||||
aux.To.Type = "Time"
|
||||
aux.To.Time = t
|
||||
|
||||
case *TypeDate:
|
||||
aux.To.Type = "Date"
|
||||
aux.To.Date = t
|
||||
|
||||
case *TypeNumber:
|
||||
aux.To.Type = "Number"
|
||||
aux.To.Number = t
|
||||
|
||||
case *TypeText:
|
||||
aux.To.Type = "Text"
|
||||
aux.To.Text = t
|
||||
|
||||
case *TypeBoolean:
|
||||
aux.To.Type = "Boolean"
|
||||
aux.To.Boolean = t
|
||||
|
||||
case *TypeEnum:
|
||||
aux.To.Type = "Enum"
|
||||
aux.To.Enum = t
|
||||
|
||||
case *TypeGeometry:
|
||||
aux.To.Type = "Geometry"
|
||||
aux.To.Geometry = t
|
||||
|
||||
case *TypeJSON:
|
||||
aux.To.Type = "JSON"
|
||||
aux.To.JSON = t
|
||||
|
||||
case *TypeBlob:
|
||||
aux.To.Type = "Blob"
|
||||
aux.To.Blob = t
|
||||
|
||||
case *TypeUUID:
|
||||
aux.To.Type = "UUID"
|
||||
aux.To.UUID = t
|
||||
}
|
||||
|
||||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
func (a *AttributeReType) UnmarshalJSON(data []byte) (err error) {
|
||||
aux := &auxAttributeReType{}
|
||||
err = json.Unmarshal(data, &aux)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a == nil {
|
||||
*a = AttributeReType{}
|
||||
}
|
||||
|
||||
a.Attr = aux.Attr
|
||||
|
||||
switch aux.To.Type {
|
||||
case "ID":
|
||||
a.To = aux.To.ID
|
||||
|
||||
case "Ref":
|
||||
a.To = aux.To.Ref
|
||||
|
||||
case "Timestamp":
|
||||
a.To = aux.To.Timestamp
|
||||
|
||||
case "Time":
|
||||
a.To = aux.To.Time
|
||||
|
||||
case "Date":
|
||||
a.To = aux.To.Date
|
||||
|
||||
case "Number":
|
||||
a.To = aux.To.Number
|
||||
|
||||
case "Text":
|
||||
a.To = aux.To.Text
|
||||
|
||||
case "Boolean":
|
||||
a.To = aux.To.Boolean
|
||||
|
||||
case "Enum":
|
||||
a.To = aux.To.Enum
|
||||
|
||||
case "Geometry":
|
||||
a.To = aux.To.Geometry
|
||||
|
||||
case "JSON":
|
||||
a.To = aux.To.JSON
|
||||
|
||||
case "Blob":
|
||||
a.To = aux.To.Blob
|
||||
|
||||
case "UUID":
|
||||
a.To = aux.To.UUID
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (a AttributeReEncode) MarshalJSON() ([]byte, error) {
|
||||
aux := auxAttributeReEncode{
|
||||
Attr: a.Attr,
|
||||
To: &auxStoreCodec{},
|
||||
}
|
||||
|
||||
switch t := a.To.(type) {
|
||||
case *CodecPlain:
|
||||
aux.To.Type = "CodecPlain"
|
||||
aux.To.CodecPlain = t
|
||||
case *CodecRecordValueSetJSON:
|
||||
aux.To.Type = "CodecRecordValueSetJSON"
|
||||
aux.To.CodecRecordValueSetJSON = t
|
||||
case *CodecAlias:
|
||||
aux.To.Type = "CodecAlias"
|
||||
aux.To.CodecAlias = t
|
||||
}
|
||||
|
||||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
func (a *AttributeReEncode) UnmarshalJSON(data []byte) (err error) {
|
||||
aux := &auxAttributeReEncode{}
|
||||
err = json.Unmarshal(data, &aux)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a == nil {
|
||||
*a = AttributeReEncode{}
|
||||
}
|
||||
|
||||
a.Attr = aux.Attr
|
||||
|
||||
switch aux.To.Type {
|
||||
case "CodecPlain":
|
||||
a.To = aux.To.CodecPlain
|
||||
|
||||
case "CodecRecordValueSetJSON":
|
||||
a.To = aux.To.CodecRecordValueSetJSON
|
||||
|
||||
case "CodecAlias":
|
||||
a.To = aux.To.CodecAlias
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (a Alteration) compare(b Alteration) (cmp bool) {
|
||||
if a.AttributeAdd == nil && b.AttributeAdd != nil {
|
||||
return false
|
||||
}
|
||||
if a.AttributeDelete == nil && b.AttributeDelete != nil {
|
||||
return false
|
||||
}
|
||||
if a.AttributeReType == nil && b.AttributeReType != nil {
|
||||
return false
|
||||
}
|
||||
if a.AttributeReEncode == nil && b.AttributeReEncode != nil {
|
||||
return false
|
||||
}
|
||||
if a.ModelAdd == nil && b.ModelAdd != nil {
|
||||
return false
|
||||
}
|
||||
if a.ModelDelete == nil && b.ModelDelete != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch {
|
||||
case a.AttributeAdd != nil:
|
||||
return a.compareAttributeAdd(b)
|
||||
case a.AttributeDelete != nil:
|
||||
return a.compareAttributeDelete(b)
|
||||
case a.AttributeReType != nil:
|
||||
return a.compareAttributeReType(b)
|
||||
case a.AttributeReEncode != nil:
|
||||
return a.compareAttributeReEncode(b)
|
||||
case a.ModelAdd != nil:
|
||||
return a.compareModelAdd(b)
|
||||
case a.ModelDelete != nil:
|
||||
return a.compareModelDelete(b)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unsupported alteration type %v", a))
|
||||
}
|
||||
|
||||
func (a Alteration) compareAttributeAdd(b Alteration) bool {
|
||||
if a.AttributeAdd == nil || b.AttributeAdd == nil {
|
||||
return a.AttributeAdd == b.AttributeAdd
|
||||
}
|
||||
return a.AttributeAdd.Attr.Compare(b.AttributeAdd.Attr)
|
||||
}
|
||||
|
||||
func (a Alteration) compareAttributeDelete(b Alteration) bool {
|
||||
if a.AttributeDelete == nil || b.AttributeDelete == nil {
|
||||
return a.AttributeDelete == b.AttributeDelete
|
||||
}
|
||||
return a.AttributeDelete.Attr.Compare(b.AttributeDelete.Attr)
|
||||
}
|
||||
|
||||
func (a Alteration) compareAttributeReType(b Alteration) bool {
|
||||
if !a.AttributeReType.Attr.Compare(b.AttributeReType.Attr) {
|
||||
return false
|
||||
}
|
||||
|
||||
if a.AttributeReType == nil || b.AttributeReType == nil {
|
||||
return a.AttributeReType == b.AttributeReType
|
||||
}
|
||||
return a.AttributeReType.To.Type() == b.AttributeReType.To.Type()
|
||||
}
|
||||
|
||||
func (a Alteration) compareAttributeReEncode(b Alteration) bool {
|
||||
if !a.AttributeReEncode.Attr.Compare(b.AttributeReEncode.Attr) {
|
||||
return false
|
||||
}
|
||||
|
||||
if a.AttributeReEncode == nil || b.AttributeReEncode == nil {
|
||||
return a.AttributeReEncode == b.AttributeReEncode
|
||||
}
|
||||
return a.AttributeReEncode.To.Type() == b.AttributeReEncode.To.Type()
|
||||
}
|
||||
|
||||
func (a Alteration) compareModelAdd(b Alteration) bool {
|
||||
if a.ModelAdd == nil || b.ModelAdd == nil {
|
||||
return a.ModelAdd == b.ModelAdd
|
||||
}
|
||||
return a.ModelAdd.Model.Compare(*b.ModelAdd.Model)
|
||||
}
|
||||
|
||||
func (a Alteration) compareModelDelete(b Alteration) bool {
|
||||
if a.ModelDelete == nil || b.ModelDelete == nil {
|
||||
return a.ModelDelete == b.ModelDelete
|
||||
}
|
||||
return a.ModelDelete.Model.Compare(*b.ModelDelete.Model)
|
||||
}
|
||||
Reference in New Issue
Block a user