Skip to content

Commit 3b53545

Browse files
committed
Added implementation of pgComment.
1 parent e49dd07 commit 3b53545

File tree

2 files changed

+86
-47
lines changed

2 files changed

+86
-47
lines changed

database/pgComment.go

Lines changed: 60 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,62 +4,79 @@ import (
44
"context"
55
"github.com/dipdup-net/go-lib/hasura"
66
"github.com/go-pg/pg/v10"
7-
"github.com/pkg/errors"
87
"reflect"
98
"strings"
109
)
1110

1211
func makeComments(ctx context.Context, conn PgGoConnection, model interface{}) error {
13-
typ := reflect.TypeOf(model)
14-
15-
// 1. go through fields
16-
// 2. if tableName field -
17-
// 2.1 read value from pg tab, if not exist from model type name with snake case convertion - remember as tableName
18-
// 2.2 read value from pg-comment tag, if not exist continue
19-
// 2.3 set comment with SQL statement
20-
// 3. other
21-
// 3.1 read comment from pg-comment, it not exist continue
22-
// 3.2 read pg tag first value if it exist, if not - then snake case name of field and set as columnName
23-
// 3.3 set comment with SQL statement
24-
for i := 0; i < typ.NumField(); i++ {
25-
fieldType := typ.Field(i)
26-
pgTag, ok := fieldType.Tag.Lookup("pg")
27-
if !ok {
28-
continue
29-
}
12+
modelType := reflect.TypeOf(model)
13+
var tableName pg.Safe
3014

31-
tags := strings.Split(pgTag, ",")
15+
for i := 0; i < modelType.NumField(); i++ {
16+
fieldType := modelType.Field(i)
3217

33-
var name string
34-
for i := range tags {
35-
if i == 0 {
36-
if name == "" {
37-
name = hasura.ToSnakeCase(fieldType.Name)
38-
} else {
39-
name = tags[i]
40-
}
41-
continue
18+
if fieldType.Name == "tableName" {
19+
20+
readFromModelName := true
21+
tableName, readFromModelName = getPgName(fieldType)
22+
if readFromModelName {
23+
tableName = pg.Safe(hasura.ToSnakeCase(modelType.Name()))
4224
}
4325

44-
parts := strings.Split(tags[i], ":")
45-
if parts[0] == "comment" {
46-
if len(parts) != 2 {
47-
return errors.Errorf("invalid comments format: %s", pgTag)
48-
}
49-
if fieldType.Name == "tableName" {
50-
// typ.Name() to
51-
if _, err := conn.DB().ExecContext(ctx, `COMMENT ON TABLE ? IS ?`, pg.Safe(typ.Name()), parts[1]); err != nil {
52-
return err
53-
}
54-
} else {
55-
if _, err := conn.DB().ExecContext(ctx, `COMMENT ON COLUMN ?.? IS ?`, pg.Safe(typ.Name()), pg.Safe(name), parts[1]); err != nil {
56-
return err
57-
}
58-
}
26+
pgCommentTag, ok := getPgComment(fieldType)
27+
if !ok {
5928
continue
6029
}
30+
31+
if _, err := conn.DB().ExecContext(ctx,
32+
`COMMENT ON TABLE ? IS ?`,
33+
tableName, pgCommentTag); err != nil {
34+
return err
35+
}
36+
37+
continue
38+
}
39+
40+
pgCommentTag, ok := getPgComment(fieldType)
41+
if !ok {
42+
continue
43+
}
44+
45+
columnName, readFromFieldName := getPgName(fieldType)
46+
if readFromFieldName {
47+
columnName = pg.Safe(hasura.ToSnakeCase(fieldType.Name))
48+
}
49+
50+
if _, err := conn.DB().ExecContext(ctx,
51+
`COMMENT ON COLUMN ?.? IS ?`,
52+
tableName, columnName, pgCommentTag); err != nil {
53+
return err
6154
}
6255
}
6356

6457
return nil
6558
}
59+
60+
func getPgName(fieldType reflect.StructField) (name pg.Safe, ok bool) {
61+
pgTag, ok := fieldType.Tag.Lookup("pg")
62+
if ok {
63+
tags := strings.Split(pgTag, ",")
64+
65+
if tags[0] != "" {
66+
name = pg.Safe(tags[0])
67+
ok = false
68+
}
69+
}
70+
71+
return name, ok
72+
}
73+
74+
func getPgComment(fieldType reflect.StructField) (pg.Safe, bool) {
75+
pgCommentTag, ok := fieldType.Tag.Lookup("pg-comment")
76+
77+
if ok {
78+
return pg.Safe(pgCommentTag), ok
79+
}
80+
81+
return "", false
82+
}

database/pgComment_test.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"github.com/go-pg/pg/v10"
66
"github.com/stretchr/testify/mock"
7+
"sort"
78
"testing"
89
)
910

@@ -25,16 +26,16 @@ type PgDBMock struct {
2526
mock.Mock
2627
}
2728

28-
func (db *PgDBMock) ExecContext(_ context.Context, query interface{}, params ...interface{}) (pg.Result, error) {
29-
args := db.Called(query, params)
29+
func (db *PgDBMock) ExecContext(ctx context.Context, query interface{}, params ...interface{}) (pg.Result, error) {
30+
args := db.Called(ctx, query, params)
3031

3132
return nil, args.Error(0)
3233
}
3334

3435
func TestMakeCommentsWithTableName(t *testing.T) {
3536
type Ballot struct {
3637
//nolint
37-
tableName struct{} `pg:"ballots"`
38+
tableName struct{} `pg:"ballots" pg-comment:"Ballot table"`
3839
Ballot string `json:"ballot"`
3940
}
4041

@@ -47,5 +48,26 @@ func TestMakeCommentsWithTableName(t *testing.T) {
4748
makeComments(ctx, pgGo, model)
4849

4950
// assert params of ExecContext
50-
pgGo.conn.AssertCalled(t, "ExecContext", ctx, `COMMENT ON TABLE ? IS ?`, "ballot", "")
51+
pgGo.conn.AssertCalled(t, "ExecContext",
52+
ctx, "COMMENT ON TABLE ? IS ?", []pg.Safe{"ballots", "Ballot table"})
53+
54+
//paramsMatcher := mock.MatchedBy(func(params []string) bool {
55+
// return IsEqual(params, []string{"ballots", "Ballot table"})
56+
//})
57+
//pgGo.conn.AssertCalled(t, "ExecContext", paramsMatcher)
58+
}
59+
60+
func IsEqual(a1 []string, a2 []string) bool {
61+
sort.Strings(a1)
62+
sort.Strings(a2)
63+
if len(a1) == len(a2) {
64+
for i, v := range a1 {
65+
if v != a2[i] {
66+
return false
67+
}
68+
}
69+
} else {
70+
return false
71+
}
72+
return true
5173
}

0 commit comments

Comments
 (0)