Skip to content

Commit

Permalink
feat: analyse extraction
Browse files Browse the repository at this point in the history
  • Loading branch information
youen committed Sep 29, 2023
1 parent dcf788d commit 4ad2e44
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 18 deletions.
1 change: 1 addition & 0 deletions cmd/lino/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func initConfig() {
zerolog.SetGlobalLevel(zerolog.Disabled)
}

analyse.Inject(tableStorage(), dataconnectorStorage(), analyseDataSourceFactory(), analyserFactory())
dataconnector.Inject(dataconnectorStorage(), dataPingerFactory())
relation.Inject(dataconnectorStorage(), relationStorage(), relationExtractorFactory())
table.Inject(dataconnectorStorage(), tableStorage(), tableExtractorFactory())
Expand Down
81 changes: 74 additions & 7 deletions internal/app/analyse/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,36 @@ package analyse

import (
"fmt"
"io"
"os"

"github.com/cgi-fr/rimo/pkg/rimo"
"github.com/cgi-fr/lino/internal/app/urlbuilder"
ianalyse "github.com/cgi-fr/lino/internal/infra/analyse"
"github.com/cgi-fr/lino/pkg/analyse"
"github.com/cgi-fr/lino/pkg/dataconnector"
"github.com/cgi-fr/lino/pkg/table"
"github.com/spf13/cobra"
)

var (
reader rimo.Reader
writer rimo.Writer
tableStorage table.Storage
dataconnectorStorage dataconnector.Storage
extractorFactories map[string]analyse.ExtractorFactory
analyserFactory analyse.AnalyserFactory
dataSourceFactory analyse.DataSourceFactory
)

// Inject dependencies
func Inject(r rimo.Reader, w rimo.Writer) {
reader = r
writer = w
func Inject(
ts table.Storage,
dbas dataconnector.Storage,
dsf map[string]analyse.ExtractorFactory,
a analyse.AnalyserFactory,
) {
tableStorage = ts
dataconnectorStorage = dbas
extractorFactories = dsf
analyserFactory = a
}

// NewCommand implements the cli analyse command
Expand All @@ -47,8 +62,23 @@ func NewCommand(fullName string, err *os.File, out *os.File, in *os.File) *cobra
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
dataConnector := args[0]
e1 := rimo.AnalyseBase(reader, writer)
dataSource, e0 := getDatasource(dataConnector)
if e0 != nil {
fmt.Fprintln(err, e0.Error())
os.Exit(1)
}

extractor, e1 := getExtractor(dataConnector, out)

if e1 != nil {
fmt.Fprintln(err, e1.Error())
os.Exit(1)
}

analyser := analyserFactory.New(out)
e2 := analyse.Do(dataSource, extractor, analyser)

if e2 != nil {
fmt.Fprintf(err, "analyse faield '%s'", dataConnector)
fmt.Fprintln(err)
os.Exit(5)
Expand All @@ -60,3 +90,40 @@ func NewCommand(fullName string, err *os.File, out *os.File, in *os.File) *cobra
cmd.SetIn(in)
return cmd
}

func getExtractor(dataconnectorName string, out io.Writer) (analyse.Extractor, error) {
alias, e1 := dataconnector.Get(dataconnectorStorage, dataconnectorName)
if e1 != nil {
return nil, e1
}
if alias == nil {
return nil, fmt.Errorf("Data Connector %s not found", dataconnectorName)
}

u := urlbuilder.BuildURL(alias, out)

datasourceFactory, ok := extractorFactories[u.UnaliasedDriver]
if !ok {
return nil, fmt.Errorf("no extractor found for database type")
}

return datasourceFactory.New(u.URL.String(), alias.Schema), nil
}

func getDatasource(dataconnectorName string) (analyse.DataSource, error) {
result := map[string][]string{}
tables, err := tableStorage.List()
if err != nil {
return nil, err
}

for _, table := range tables {
columns := []string{}
for _, column := range table.Columns {
columns = append(columns, column.Name)
}
result[table.Name] = columns
}

return ianalyse.NewMapDataSource(dataconnectorName, result), nil
}
20 changes: 16 additions & 4 deletions pkg/analyse/driven.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,31 @@

package analyse

import "io"

type ExtractorFactory interface {
New(url string, schema string) Extractor
}

type DataSource interface {
Name() string
ListTables() []string
ListColumn(tableName string) []string
ExtractValues(columnName string) []interface{}
}

type Extractor interface {
ExtractValues(tableName string, columnName string) []interface{}
}

type AnalyserFactory interface {
New(io.Writer) Analyser
}

// Analyser is the provider of statistics analyse
type Analyser interface {
Analyse(ds *ColumnIterator) error
}

// Reporter is the provider of reporting result of the analyse
type Reporter interface {
Export() error
type DataSourceFactory interface {
New() DataSource
}
10 changes: 6 additions & 4 deletions pkg/analyse/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,24 @@
package analyse

// Do performe statistics on datasource.
func Do(ds DataSource, analyser Analyser) error {
iterator := NewColumnIterator(ds)
func Do(ds DataSource, ex Extractor, analyser Analyser) error {
iterator := NewColumnIterator(ds, ex)
return analyser.Analyse(iterator)
}

type ColumnIterator struct {
tables []string
column []string
DataSource
Extractor
}

func NewColumnIterator(ds DataSource) *ColumnIterator {
func NewColumnIterator(ds DataSource, ex Extractor) *ColumnIterator {
return &ColumnIterator{
tables: []string{},
column: []string{},
DataSource: ds,
Extractor: ex,
}
}

Expand Down Expand Up @@ -69,5 +71,5 @@ func (ci *ColumnIterator) Next() bool {

// Value return the column content.
func (ci *ColumnIterator) Value() ([]interface{}, string, string, error) {
return ci.DataSource.ExtractValues(ci.column[0]), ci.tables[0], ci.column[0], nil
return ci.ExtractValues(ci.tables[0], ci.column[0]), ci.tables[0], ci.column[0], nil
}
10 changes: 7 additions & 3 deletions pkg/analyse/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ func (tds *testDataSource) ListColumn(tableName string) []string {
return []string{"col1", "col2"}
}

func (tds *testDataSource) ExtractValues(columnName string) []interface{} {
type testExtractor struct{}

func (tds *testExtractor) ExtractValues(tableName string, columnName string) []interface{} {
return []interface{}{1., 2., 3., 4., 5.}
}

Expand All @@ -69,10 +71,11 @@ func (tw *testWriter) Export(report *model.Base) error {
func TestAnalyseShouldNotReturnError(t *testing.T) {
t.Parallel()
dataSource := &testDataSource{}
extractor := &testExtractor{}
writer := &testWriter{}
analyser := rimoAnalyser{writer}

err := analyse.Do(dataSource, analyser)
err := analyse.Do(dataSource, extractor, analyser)

assert.Nil(t, err)
assert.NotNil(t, writer.result)
Expand All @@ -85,8 +88,9 @@ func TestColumnIteratorNext(t *testing.T) {
t.Parallel()

dataSource := &testDataSource{}
extractor := &testExtractor{}

iterator := analyse.NewColumnIterator(dataSource)
iterator := analyse.NewColumnIterator(dataSource, extractor)

for table := 1; table < 3; table++ {
for c := 1; c < 3; c++ {
Expand Down

0 comments on commit 4ad2e44

Please sign in to comment.