Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Docugraphy
Docugraphy is a framework for modeling a data structure consisting of a wide, although sparsely filled, records.
The assumption is that the content filling the structure takes many forms, that are quasi-defined subsets of the available attributes/columns.
The assumption is that the content filling the structure takes many forms, that are quasi-defined subsets of the available attributes/columns.

## Schema


26 changes: 15 additions & 11 deletions model/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,22 @@ const (
Decommisioned // Removed from PROD
)

type ImplementationStatusDictionary struct {
Id ImplementationStatus `sql:",pk"`
Status string // Arbitrary name/tag for the source system
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

source system? not status'?

Description string // What the source system represents, it's job/competence
}

//Definition of a source system that produces data feeding the wide-row.
type SourceSystem struct {
Id uint32 `json:"-"`
Name string `sql:",unique"` // Arbitrary name/tag for the source system
Name string `sql:",pk"` // Arbitrary name/tag for the source system
Description string // What the source system represents, it's job/competence
}

// An event type is a data structure consisting of a subset of fields available in the wide-row structure.
// This structure represents the canonical definition of the event type.
type EventType struct {
Id uint64 `json:"-"`
Name string `sql:",unique"` // The name of a event_type according to the wide-row design
Name string `sql:",pk"` // The name of a event_type according to the wide-row design
RecommendedUse string // The explanation of how to use this event type in terms of its universal business definition
Status ImplementationStatus //What is the status of the event type on a receiving point (data lake)
}
Expand All @@ -32,18 +36,17 @@ type EventTypeImplementation struct {
PreciseUse string //The explanation of how to use this event type in terms of its business definition according to a certain source system
Status ImplementationStatus //What is the status of the event type on a sending point (source system)

EventTypeId uint64 `sql:"on_delete:RESTRICT, on_update: CASCADE, pk"` // Reference to the canonical definition of an event type
EventTypeName string `sql:"on_delete:RESTRICT, on_update: CASCADE, pk"` // Reference to the canonical definition of an event type
EventType *EventType

SourceSystemId uint32 `sql:"on_delete:RESTRICT, on_update: CASCADE, pk"` // Reference to a source system that the implementation refers to
SourceSystemName string `sql:"on_delete:RESTRICT, on_update: CASCADE, pk"` // Reference to a source system that the implementation refers to
SourceSystem *SourceSystem
}

// Definition of a field/attribute within the wide-row structure.
// This structure represents the canonical definition of the field.
type Field struct {
Id uint64 `json:"-"`
Name string `sql:",unique"` // The name of a field according to the wide-row design
Name string `sql:",pk"` // The name of a field according to the wide-row design
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are you going to distinguish between 2 fields with the same name - the first one being a 'top level' field and the the other one being nested somewhere? Will Name contain the entire field path so field_A and field_B.field_A will end up having different Names?

Type string // Data type of the field
RecommendedUse string // The explanation of how to use this field in terms of its universal business definition
Status ImplementationStatus //What is the status of the field on a receiving point (data lake)
Expand All @@ -54,11 +57,12 @@ type FieldImplementation struct {
PreciseUse string //The explanation of how to use this field in terms of its business definition according to a certain source system
Status ImplementationStatus //What is the status of the field on a sending point (source system)

FieldId uint64 `sql:"on_delete:RESTRICT, on_update: CASCADE, pk"`
FieldName string `sql:"on_delete:RESTRICT, on_update: CASCADE, pk"`
Field *Field

SourceSystemId uint32 `sql:"on_delete:RESTRICT, on_update: CASCADE, pk"`
SourceSystem *SourceSystem
EventTypeName string `sql:"on_delete:RESTRICT, on_update: CASCADE, pk"`
SourceSystemName string `sql:"on_delete:RESTRICT, on_update: CASCADE, pk"`
EventTypeImplementation *EventTypeImplementation
}

// Definition of a value from a restricted list that applies for a certain field (and source system)
Expand Down
15 changes: 15 additions & 0 deletions repository/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ type Repository interface {
Connect()
Disconnect() error
SetupSchema() error

GetSourceSystems() ([]model.SourceSystem, error)
GetEventTypes() ([]model.EventType, error)
GetFields() ([]model.Field, error)
GetEventTypeImplementations(sourceSystemName string) ([]model.EventTypeImplementation, error)
GetFieldImplementations(sourceSystemName string, fieldName string) ([]model.FieldImplementation, error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it really be taking sourceSystemName? fieldImplementation is already connecting a sourceSystem with a field so if you provide both sourceSystemName and fieldName to this function you'll end up with either 0 or 1 FieldImplementations.

Edit: OK, my bad - I didn't notice the EventTypeName in fieldImplementation... maybe because I'm not convinced that it's a good idea to have it there in the first place.


AddSourceSystem(sourceSystem *model.SourceSystem) error
AddEventType(eventType *model.EventType) error
AddField(field *model.Field) error
AddEventTypeImplementation(eventTypeImplementation *model.EventTypeImplementation) error
AddFieldImplementation(fieldImplementation *model.FieldImplementation) error

ChangeStatusOfEventType(eventTypeName string, status model.ImplementationStatus) error
ChangeStatusOfField(fieldName string, status model.ImplementationStatus) error
ChangeStatusOfEventTypeImplementation(eventTypeName string, sourceSystemName string, status model.ImplementationStatus) error
ChangeStatusOfFieldImplementation(fieldName string, eventTypeName string, sourceSystem string, status model.ImplementationStatus) error
}
198 changes: 198 additions & 0 deletions repository/postgres/create_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func (pr *Repository) SetupSchema() error {
(*model.Field)(nil),
(*model.FieldImplementation)(nil),
(*model.RestrictedValue)(nil),
(*model.ImplementationStatusDictionary)(nil),
} {
err := pr.Connection.CreateTable(entity, &orm.CreateTableOptions{
FKConstraints: true,
Expand All @@ -54,6 +55,107 @@ func (pr *Repository) GetSourceSystems() ([]model.SourceSystem, error) {
return sourceSystem, nil
}

func (pr *Repository) GetEventTypes() ([]model.EventType, error) {
var eventType []model.EventType

err := pr.Connection.Model(&eventType).Select()
if err != nil {
return nil, err
}
return eventType, nil
}

func (pr *Repository) getEventType(eventTypeName string) (model.EventType, error) {
eventType := model.EventType{}

err := pr.Connection.Model(&eventType).
Where("event_type.name = ?", eventTypeName).
Select()
if err != nil {
return eventType, err
}
return eventType, nil
}

func (pr *Repository) GetFields() ([]model.Field, error) {
var fields []model.Field

err := pr.Connection.Model(&fields).Select()
if err != nil {
return nil, err
}
return fields, nil
}

func (pr *Repository) getField(fieldName string) (model.Field, error) {
field := model.Field{}

err := pr.Connection.Model(&field).
Where("field.name = ?", fieldName).
Select()
if err != nil {
return field, err
}
return field, nil
}

func (pr *Repository) GetEventTypeImplementations(sourceSystemName string) ([]model.EventTypeImplementation, error) {
var eventTypeImplementations []model.EventTypeImplementation

err := pr.Connection.
Model(&eventTypeImplementations).
Where("event_type_implementation.source_system = ?", sourceSystemName).
Select()
if err != nil {
return nil, err
}
return eventTypeImplementations, nil
}

func (pr *Repository) getEventTypeImplementation(sourceSystemName string, eventTypeName string) (model.EventTypeImplementation, error) {
eventTypeImplementation := model.EventTypeImplementation{}

err := pr.Connection.
Model(&eventTypeImplementation).
Where("event_type_implementation.source = ?", sourceSystemName).
Where("event_type_implementation.event_type_name = ?", eventTypeName).
Select()
if err != nil {
return eventTypeImplementation, err
}
return eventTypeImplementation, nil
}

func (pr *Repository) GetFieldImplementations(sourceSystemName string, eventTypeName string) ([]model.FieldImplementation, error) {
var fieldImplementations []model.FieldImplementation

err := pr.Connection.
Model(&fieldImplementations).
Column("event_type_implementation").
Where("event_type_implementation.source = ?", sourceSystemName).
Where("event_type_implementation.event_type_name = ?", eventTypeName).
Select("field.*")
if err != nil {
return nil, err
}
return fieldImplementations, nil
}

func (pr *Repository) getFieldImplementation(sourceSystemName string, eventTypeName string, fieldName string) (model.FieldImplementation, error) {
fieldImplementation := model.FieldImplementation{}

err := pr.Connection.
Model(&fieldImplementation).
Where("field_implementation.source = ?", sourceSystemName).
Where("field_implementation.event_type_name = ?", eventTypeName).
Where("field_implementation.field_name = ?", fieldName).
Select()
if err != nil {
return fieldImplementation, err
}
return fieldImplementation, nil
}

func (pr *Repository) AddSourceSystem(sourceSystem *model.SourceSystem) error {
err := pr.Connection.Insert(sourceSystem)
if err != nil {
Expand All @@ -62,3 +164,99 @@ func (pr *Repository) AddSourceSystem(sourceSystem *model.SourceSystem) error {
log.Println("Inserted new Source System: ", sourceSystem.Name)
return nil
}

func (pr *Repository) AddEventType(eventType *model.EventType) error {
err := pr.Connection.Insert(eventType)
if err != nil {
return err
}
log.Println("Inserted new Event Type: ", eventType.Name)
return nil
}

func (pr *Repository) AddField(field *model.Field) error {
err := pr.Connection.Insert(field)
if err != nil {
return err
}
log.Println("Inserted new Field: ", field.Name)
return nil
}

func (pr *Repository) AddEventTypeImplementation(eventTypeImplementation *model.EventTypeImplementation) error {
err := pr.Connection.Insert(eventTypeImplementation)
if err != nil {
return err
}
log.Println("Inserted new Event Type Implementation with Event Type: ",
eventTypeImplementation.EventTypeName,
", and source system: ",
eventTypeImplementation.SourceSystemName)
return nil
}

func (pr *Repository) AddFieldImplementation(fieldImplementation *model.FieldImplementation) error {
err := pr.Connection.Insert(fieldImplementation)
if err != nil {
return err
}
log.Println("Inserted new Event Type Implementation with Event Type: ",
fieldImplementation.EventTypeName,
", and field: ",
fieldImplementation.FieldName,
", and source system: ",
fieldImplementation.SourceSystemName)
return nil
}

func (pr *Repository) ChangeStatusOfEventType(eventTypeName string, status model.ImplementationStatus) error {
eventType, err := pr.getEventType(eventTypeName)
if err != nil {
return err
}
eventType.Status = status
err = pr.Connection.Update(&eventType)
if err != nil {
return err
}
return nil
}

func (pr *Repository) ChangeStatusOfField(fieldName string, status model.ImplementationStatus) error {
field, err := pr.getField(fieldName)
if err != nil {
return err
}
field.Status = status
err = pr.Connection.Update(&field)
if err != nil {
return err
}
return nil
}

func (pr *Repository) ChangeStatusOfEventTypeImplementation(eventTypeName string, sourceSystem string, status model.ImplementationStatus) error {
eventTypeImplementation, err := pr.getEventTypeImplementation(eventTypeName, sourceSystem)
if err != nil {
return err
}
eventTypeImplementation.Status = status
err = pr.Connection.Update(&eventTypeImplementation)
if err != nil {
return err
}
return nil
}

func (pr *Repository) ChangeStatusOfFieldImplementation(fieldName string, eventTypeName string, sourceSystem string, status model.ImplementationStatus) error {
fieldImplementation, err := pr.getFieldImplementation(fieldName, eventTypeName, sourceSystem)
if err != nil {
return err
}
fieldImplementation.Status = status
err = pr.Connection.Update(&fieldImplementation)
if err != nil {
return err
}
return nil
}
12 changes: 6 additions & 6 deletions repository/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,30 @@ import (
"fmt"
)

var dbRepo Repository
var DbRepo Repository

func Create() error {
err := dbRepo.SetupSchema()
err := DbRepo.SetupSchema()
return err
}

func Connect() error {
var err error = nil
switch dbType := config.GetConfig().DbType; dbType {
case TypeNamePostgres:
dbRepo = postgres.Build()
DbRepo = postgres.Build()
default:
err = fmt.Errorf("Unknown database id %s\n", dbType)
return err
}
dbRepo.Connect()
DbRepo.Connect()
return err
}

func GetSourceSystems() ([]model.SourceSystem, error) {
return dbRepo.GetSourceSystems()
return DbRepo.GetSourceSystems()
}

func AddSourceSystem(sourceSystem *model.SourceSystem) error {
return dbRepo.AddSourceSystem(sourceSystem)
return DbRepo.AddSourceSystem(sourceSystem)
}
1 change: 1 addition & 0 deletions schema.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<mxfile modified="2019-06-03T18:00:52.405Z" host="www.draw.io" agent="Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0" etag="F4gfTq2iRnicEcgrqMII" version="10.7.4" type="device"><diagram id="Wph7SEo1UGMb8BsfoMnq" name="Page-1">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</diagram></mxfile>