Skip to content

Commit

Permalink
added columns config to the sqlx
Browse files Browse the repository at this point in the history
  • Loading branch information
klarysz committed Jul 14, 2022
1 parent b636050 commit 97ad591
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 36 deletions.
2 changes: 1 addition & 1 deletion cmd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ JOIN (SELECT ID, NAME, DEPT_ID,
'x1,x2'
WHEN COLUMN_X = 2 THEN
'x3,x4'
END) AS SLICE /* {"Codec":{"Ref":"AsStrings"}} */
END) AS SLICE /* {"Codec":{"Ref":"AsStrings"}, "DataType": "string"} */
FROM EMP t) employee ON dept.ID = employee.DEPT_ID
JOIN ORG organization ON organization.ID = demp.ORG_ID AND 1=1
WHERE ID = $Id
Expand Down
6 changes: 3 additions & 3 deletions cmd/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/viant/afs"
"github.com/viant/afs/file"
"github.com/viant/afs/mem"
"github.com/viant/datly/gateway"
"github.com/viant/datly/gateway/runtime/standalone"
"github.com/viant/datly/router/openapi3"
Expand Down Expand Up @@ -43,8 +44,6 @@ type testcase struct {
dataMethod string
}

//TODO: afs caches generated routes, it makes every test case depends on previous.
//TODO: clean afs cache after every run, currently it is needed to run one by one.
func TestRun(t *testing.T) {
TimeNow = func() time.Time {
parse, _ := time.Parse("2006-01-02 15:04:05.000000000 -0700 MST", "2014-11-12 11:45:26.000000000 +0000 UTC")
Expand Down Expand Up @@ -87,7 +86,8 @@ func TestRun(t *testing.T) {

loader := afs.New()
//for i, testCase := range testCases[len(testCases)-1:] {
for i, testCase := range testCases[:1] {
for i, testCase := range testCases {
mem.ResetSingleton()
gateway.ResetSingleton()

fmt.Printf("Running testcase: %v\n", i)
Expand Down
52 changes: 49 additions & 3 deletions cmd/relation.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"github.com/viant/afs"
"github.com/viant/afs/file"
Expand All @@ -13,10 +14,12 @@ import (
"github.com/viant/datly/view"
"github.com/viant/sqlx/io"
"github.com/viant/sqlx/metadata"
"github.com/viant/sqlx/metadata/ast/parser"
"github.com/viant/sqlx/metadata/info"
"github.com/viant/sqlx/metadata/sink"
"github.com/viant/sqlx/option"
rdata "github.com/viant/toolbox/data"
"github.com/viant/toolbox/format"
"reflect"
"strings"
)
Expand Down Expand Up @@ -55,6 +58,12 @@ func buildXRelations(options *Options, route *router.Resource, viewRoute *router
if aView == nil {
return fmt.Errorf("failed to lookup view: %v", join.Owner.Name)
}

newCase, err := format.NewCase(view.DetectCase(join.Table.Alias))
if err != nil {
return err
}

aView.With = append(aView.With, &view.Relation{
Name: aView.Name + "_" + join.Table.Alias,
Of: &view.ReferenceView{
Expand All @@ -65,7 +74,7 @@ func buildXRelations(options *Options, route *router.Resource, viewRoute *router
Cardinality: cardinality,
Column: join.OwnerKey,
ColumnAlias: join.KeyAlias,
Holder: strings.Title(join.Table.Alias),
Holder: newCase.Format(join.Table.Alias, format.CaseUpperCamel),

IncludeColumn: true,
})
Expand All @@ -82,6 +91,10 @@ func updateView(options *Options, table *Table, aView *view.View) error {
updateTableColumnTypes(options, table)
updateParameterTypes(table)

if err := updateColumnsConfig(table, aView); err != nil {
return err
}

if viewMeta := table.ViewMeta; viewMeta != nil {
var SQL string
var err error
Expand Down Expand Up @@ -146,6 +159,34 @@ func updateView(options *Options, table *Table, aView *view.View) error {
return nil
}

func updateColumnsConfig(table *Table, aView *view.View) error {
query, err := parser.ParseQuery(table.SQL)
if err != nil {
return err
}

aView.ColumnsConfig = map[string]*view.ColumnConfig{}
for _, item := range query.List {

if item.Comments == "" {
continue
}

configJSON := strings.TrimPrefix(item.Comments, "/*")
configJSON = strings.TrimSuffix(configJSON, "*/")
configJSON = strings.TrimSpace(configJSON)

aConfig := &view.ColumnConfig{}
if err := json.Unmarshal([]byte(configJSON), aConfig); err != nil {
fmt.Printf(err.Error())
continue
}

aView.ColumnsConfig[item.Alias] = aConfig
}
return nil
}

func updateTableColumnTypes(options *Options, table *Table) {
//TODO read all column per alias from main and join table
table.ColumnTypes = map[string]string{}
Expand Down Expand Up @@ -181,7 +222,6 @@ func updateTableColumnTypes(options *Options, table *Table) {
}

func createAndEvalauteTemplate(meta *ast.ViewMeta) (string, error) {

schemaFields := make([]reflect.StructField, len(meta.Parameters))
presenceFields := make([]reflect.StructField, len(meta.Parameters))

Expand Down Expand Up @@ -284,6 +324,12 @@ func buildRelations(options *Options, meta *metadata.Service, db *sql.DB, route
},
}
route.Resource.AddViews(relView)

caseFormat, err := format.NewCase(view.DetectCase(relName))
if err != nil {
return err
}

aView.With = append(aView.With, &view.Relation{
Name: aView.Name + relName,
Of: &view.ReferenceView{
Expand All @@ -292,7 +338,7 @@ func buildRelations(options *Options, meta *metadata.Service, db *sql.DB, route
},
Cardinality: view.Many,
Column: parentColumn,
Holder: strings.Title(relName),
Holder: caseFormat.Format(relName, format.CaseUpperCamel),
})

viewRoute.Index.Namespace[namespace(relTable)] = relName + "#"
Expand Down
2 changes: 1 addition & 1 deletion cmd/testdata/case002_one_to_one/expected.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"id":1,"timestamp":"2019-03-11T02:20:33Z","eventTypeId":2,"quantity":33.23432374000549,"userId":1,"event_types":[{"id":2,"name":"type 6","accountId":37}]},{"id":10,"timestamp":"2019-03-15T12:07:33Z","eventTypeId":11,"quantity":21.957962334156036,"userId":2,"event_types":[{"id":11,"name":"type 2","accountId":33}]},{"id":100,"timestamp":"2019-04-10T05:15:33Z","eventTypeId":111,"quantity":5.084940046072006,"userId":3,"event_types":[{"id":111,"name":"type 3","accountId":36}]}]
[{"id":1,"timestamp":"2019-03-11T02:20:33Z","eventTypeId":2,"quantity":33.23432374000549,"userId":1,"eventTypes":[{"id":2,"name":"type 6","accountId":37}]},{"id":10,"timestamp":"2019-03-15T12:07:33Z","eventTypeId":11,"quantity":21.957962334156036,"userId":2,"eventTypes":[{"id":11,"name":"type 2","accountId":33}]},{"id":100,"timestamp":"2019-04-10T05:15:33Z","eventTypeId":111,"quantity":5.084940046072006,"userId":3,"eventTypes":[{"id":111,"name":"type 3","accountId":36}]}]
3 changes: 2 additions & 1 deletion cmd/testdata/case002_one_to_one/log.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Resource:
With:
- Cardinality: Many
Column: event_type_id
Holder: Event_types
Holder: EventTypes
Name: eventsevent_types
Of:
Column: id
Expand All @@ -84,6 +84,7 @@ Routes:
- '*'
ExposeHeaders:
- '*'
EnableAudit: false
Method: GET
Namespace:
ty: event_types#
Expand Down
2 changes: 1 addition & 1 deletion cmd/testdata/case002_one_to_one/view.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Template:
With:
- Cardinality: Many
Column: event_type_id
Holder: Event_types
Holder: EventTypes
Name: eventsevent_types
Of:
Alias: t
Expand Down
13 changes: 7 additions & 6 deletions cmd/testdata/case003_columns_codec/events.sql
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
SELECT events.*
-- event_type.*
SELECT events.*,
event_type.*
FROM (
SELECT id,
name,
event_type_id,
(CASE
WHEN COLUMN_X = 1 THEN
WHEN id = 1 THEN
'x1,x2'
WHEN COLUMN_X = 2 THEN
ELSE
'x3,x4'
END) AS slice /* {"Codec":{"Ref":"AsStrings"}} */
END) AS slice /* {"Codec":{"Ref":"AsStrings"}, "DataType": "string"} */
FROM events
) events
JOIN event_types event_type ON events.event_type_id = event_type.id
1 change: 1 addition & 0 deletions cmd/testdata/case003_columns_codec/expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"id":1,"event_type_id":2,"slice":["x1","x2"],"eventType":[{"id":2,"name":"type 6","accountId":37}]},{"id":10,"event_type_id":11,"slice":["x3","x4"],"eventType":[{"id":11,"name":"type 2","accountId":33}]},{"id":100,"event_type_id":111,"slice":["x3","x4"],"eventType":[{"id":111,"name":"type 3","accountId":36}]}]
20 changes: 20 additions & 0 deletions cmd/testdata/case003_columns_codec/log.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ Resource:
ModTime: "0001-01-01T00:00:00Z"
Views:
- CaseFormat: lc
ColumnsConfig:
slice:
Codec:
Ref: AsStrings
DataType: string
Connector:
Ref: dev
FromURL: events_from.sql
Expand All @@ -62,6 +67,20 @@ Resource:
Limit: 40
Table: events
UseBindingPositions: true
With:
- Cardinality: Many
Column: event_type_id
Holder: EventType
IncludeColumn: true
Name: events_event_type
Of:
Column: id
Name: event_type#
Ref: event_type
- Name: event_type
Selector:
Limit: 40
Table: event_types
Routes:
- Cardinality: Many
CaseFormat: lc
Expand All @@ -79,6 +98,7 @@ Routes:
Method: GET
Namespace:
ev: events
ty: event_type#
Style: Basic
URI: /v1/api/dev/events
View:
Expand Down
55 changes: 38 additions & 17 deletions cmd/testdata/case003_columns_codec/view.yaml
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
Alias: t
Batch:
Parent: 10000
CaseFormat: lu
Caser: 5
CaseFormat: lc
Caser: 3
Columns:
- DataType: INTEGER
Filterable: true
Name: id
Nullable: true
- DataType: DATETIME
Filterable: true
Name: timestamp
Nullable: true
- DataType: INTEGER
Filterable: true
Name: event_type_id
Nullable: true
- DataType: DECIMAL(7, 2)
Filterable: true
Name: quantity
Nullable: true
- DataType: INTEGER
- Codec:
Name: AsStrings
Ref: AsStrings
Schema:
Cardinality: One
DataType: string
Filterable: true
Name: user_id
Name: slice
Nullable: true
ColumnsConfig:
slice:
Codec:
Name: AsStrings
Ref: AsStrings
Schema:
Cardinality: One
DataType: string
Expression: null
Name: ""
Connector:
DSN: /tmp/datly/generator/db.db
Driver: sqlite3
Expand All @@ -32,6 +39,8 @@ Connector:
Data: null
Key: blowfish://default
URL: mem://localhost/resource/mysql.json
From: "SELECT id,\n event_type_id,\n (CASE\n WHEN id = 1 THEN\n 'x1,x2'\n ELSE\n 'x3,x4'\n END) AS slice /* {\"Codec\":{\"Ref\":\"AsStrings\"}, \"DataType\": \"string\"} */\n FROM events\n "
FromURL: events_from.sql
Logger:
Name: ""
MatchStrategy: read_matched
Expand All @@ -54,12 +63,24 @@ Template:
Cardinality: One
Schema:
Cardinality: One
Source: events
Source: |-
(SELECT id,
event_type_id,
(CASE
WHEN id = 1 THEN
'x1,x2'
ELSE
'x3,x4'
END) AS slice /* {"Codec":{"Ref":"AsStrings"}, "DataType": "string"} */
FROM events
)
UseBindingPositions: true
With:
- Cardinality: Many
Column: event_type_id
Holder: Event_types
Name: eventsevent_types
Holder: EventType
IncludeColumn: true
Name: events_event_type
Of:
Alias: t
Batch:
Expand Down Expand Up @@ -89,8 +110,8 @@ With:
Logger:
Name: ""
MatchStrategy: read_matched
Name: event_types#
Ref: event_types
Name: event_type#
Ref: event_type
Schema:
Cardinality: One
Selector:
Expand Down
14 changes: 11 additions & 3 deletions view/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,20 @@ func (c *Column) Init(resource *Resource, caser format.Case, allowNulls bool, co
return fmt.Errorf("column name was empty")
}

if c.rType == nil {
nonPtrType := c.rType
for nonPtrType != nil && nonPtrType.Kind() == reflect.Ptr {
nonPtrType = nonPtrType.Elem()
}

if nonPtrType == nil || nonPtrType.Kind() == reflect.Interface {
rType, err := ParseType(c.DataType)
if err != nil {
if err != nil && c.rType == nil {
return err
}
c.rType = rType

if rType != nil {
c.rType = rType
}
}

if err := c.buildSQLExpression(allowNulls); err != nil {
Expand Down
4 changes: 4 additions & 0 deletions view/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,10 @@ func (v *View) inherit(view *View) error {
v.Cache = &shallowCopy
}

if v.ColumnsConfig == nil {
v.ColumnsConfig = view.ColumnsConfig
}

return nil
}

Expand Down

0 comments on commit 97ad591

Please sign in to comment.