forked from kyma-incubator/compass
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dao.go
152 lines (128 loc) · 3.81 KB
/
dao.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package application
import (
"context"
"fmt"
sq "github.com/Masterminds/squirrel"
"github.com/jmoiron/sqlx"
"github.com/kyma-incubator/compass/docs/investigations/storage/sql-toolbox/libs/sqlx/internal/db"
"github.com/kyma-incubator/compass/docs/investigations/storage/sql-toolbox/libs/sqlx/internal/dto"
"github.com/kyma-incubator/compass/docs/investigations/storage/sql-toolbox/libs/sqlx/internal/model"
"github.com/lann/builder"
)
func NewApplicationDao(db *sqlx.DB) *Dao {
return &Dao{
db: db,
}
}
type Dao struct {
db *sqlx.DB
}
func (d *Dao) GetApplications(ctx context.Context, p model.PageRequest, sel model.Filer) (*model.ApplicationPage, error) {
var apps []dto.ApplicationDTO
// squirrel usage example
selBuilder := sq.Select("*").From("applications").Where("labels->>'group'=$1","default")
// how to generate "totalCount" query
//totalCnt := d.getTotalCountQuery(selBuilder)
str, args, err := selBuilder.ToSql()
if err != nil {
return nil, err
}
err = d.db.Select(&apps, str, args...)
if err != nil {
return nil, err
}
var out []model.Application
for _, app := range apps {
out = append(out, app.ToModel())
}
return &model.ApplicationPage{Data: out}, nil
}
func (d *Dao) CreateApplication(ctx context.Context, app model.Application) (*model.Application, error) {
idp := db.IDProvider{}
id, err := idp.GenID()
if err != nil {
return nil, err
}
appDTO := dto.ApplicationFromModel(app)
appDTO.ID = id
app.ID = id
txx, err := d.db.Beginx()
if err != nil {
return nil, err
}
txStatus := &txStatus{}
defer d.rollbackIfNeeded(txStatus, txx) // TODO I have to implement it on my own, to avoid rollbacking on every error
// TODO: I have to specify all fields explicitly here to be persisted
_, err = txx.NamedExecContext(ctx, "insert into applications(id,tenant,name,description,labels) values (:id, :tenant, :name, :description, :labels)", appDTO)
if err != nil {
return nil, err
}
if app.Apis.Data != nil {
for _, a := range app.Apis.Data {
apiDTO := dto.APIFromModel(app.ID, a)
id, err := idp.GenID()
if err != nil {
return nil, err
}
apiDTO.ID = id
a.ID = id
apiDTO.AppID = app.ID
_, err = txx.NamedExecContext(ctx, "insert into apis(id, app_id, target_url) values(:id,:appid, :targeturl)", apiDTO) //TODO
if err != nil {
return nil, err
}
}
}
if app.Documents.Data != nil {
for _, d := range app.Documents.Data {
dDTO := dto.DocumentFromModel(app.ID, d)
id, err := idp.GenID()
if err != nil {
return nil, err
}
dDTO.ID = id
d.ID = id
_, err = txx.NamedExecContext(ctx, "insert into documents(id,app_id, title, format,data) values(:id, :appid, :title, :format, :data)", dDTO)
if err != nil {
return nil, err
}
}
}
if err := txx.Commit(); err != nil {
return nil, err
}
txStatus.Committed = true
return &app, nil
}
func (d *Dao) DeleteApplication(ctx context.Context, id string) (bool, error) {
res, err := d.db.NamedExecContext(ctx, "delete from applications where id= :id", map[string]interface{}{"id": id})
if err != nil {
panic(err)
}
aff, err := res.RowsAffected()
switch aff {
case 0:
return false, nil
case 1:
return true, nil
default:
return false, fmt.Errorf("incorrect number of removed applications: %d", aff)
}
}
// TODO workaround how to generate query that returns total count
func (d *Dao) getTotalCountQuery(originalQuery sq.SelectBuilder) sq.SelectBuilder {
countQuery := originalQuery.RemoveOffset().RemoveLimit()
return builder.Set(countQuery, "Columns", []sq.Sqlizer{stringSqlizer("count(*)")}).(sq.SelectBuilder)
}
type stringSqlizer string
func (s stringSqlizer) ToSql() (string, []interface{}, error) {
return string(s), nil, nil
}
func (d *Dao) rollbackIfNeeded(status *txStatus, tx *sqlx.Tx) {
if !status.Committed {
tx.Rollback()
}
}
type txStatus struct {
Committed bool
}