github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/operation_sql.go (about) 1 // Copyright © 2021 Kaleido, Inc. 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package sqlcommon 18 19 import ( 20 "context" 21 "database/sql" 22 23 sq "github.com/Masterminds/squirrel" 24 "github.com/kaleido-io/firefly/internal/i18n" 25 "github.com/kaleido-io/firefly/internal/log" 26 "github.com/kaleido-io/firefly/pkg/database" 27 "github.com/kaleido-io/firefly/pkg/fftypes" 28 ) 29 30 var ( 31 opColumns = []string{ 32 "id", 33 "tx_id", 34 "optype", 35 "opstatus", 36 "member", 37 "plugin", 38 "backend_id", 39 "created", 40 "updated", 41 "error", 42 "info", 43 } 44 opFilterTypeMap = map[string]string{ 45 "tx": "tx_id", 46 "type": "optype", 47 "status": "opstatus", 48 "backendid": "backend_id", 49 } 50 ) 51 52 func (s *SQLCommon) UpsertOperation(ctx context.Context, operation *fftypes.Operation, allowExisting bool) (err error) { 53 54 ctx, tx, autoCommit, err := s.beginOrUseTx(ctx) 55 if err != nil { 56 return err 57 } 58 defer s.rollbackTx(ctx, tx, autoCommit) 59 60 existing := false 61 if allowExisting { 62 // Do a select within the transaction to detemine if the UUID already exists 63 opRows, err := s.queryTx(ctx, tx, 64 sq.Select("id"). 65 From("operations"). 66 Where(sq.Eq{"id": operation.ID}), 67 ) 68 if err != nil { 69 return err 70 } 71 72 existing = opRows.Next() 73 opRows.Close() 74 } 75 76 if existing { 77 // Update the operation 78 if err = s.updateTx(ctx, tx, 79 sq.Update("operations"). 80 Set("tx_id", operation.Transaction). 81 Set("optype", operation.Type). 82 Set("opstatus", operation.Status). 83 Set("member", operation.Member). 84 Set("plugin", operation.Plugin). 85 Set("backend_id", operation.BackendID). 86 Set("created", operation.Created). 87 Set("updated", operation.Updated). 88 Set("error", operation.Error). 89 Set("info", operation.Info). 90 Where(sq.Eq{"id": operation.ID}), 91 ); err != nil { 92 return err 93 } 94 } else { 95 if _, err = s.insertTx(ctx, tx, 96 sq.Insert("operations"). 97 Columns(opColumns...). 98 Values( 99 operation.ID, 100 operation.Transaction, 101 string(operation.Type), 102 string(operation.Status), 103 operation.Member, 104 operation.Plugin, 105 operation.BackendID, 106 operation.Created, 107 operation.Updated, 108 operation.Error, 109 operation.Info, 110 ), 111 ); err != nil { 112 return err 113 } 114 } 115 116 return s.commitTx(ctx, tx, autoCommit) 117 } 118 119 func (s *SQLCommon) opResult(ctx context.Context, row *sql.Rows) (*fftypes.Operation, error) { 120 var op fftypes.Operation 121 err := row.Scan( 122 &op.ID, 123 &op.Transaction, 124 &op.Type, 125 &op.Status, 126 &op.Member, 127 &op.Plugin, 128 &op.BackendID, 129 &op.Created, 130 &op.Updated, 131 &op.Error, 132 &op.Info, 133 ) 134 if err != nil { 135 return nil, i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "operations") 136 } 137 return &op, nil 138 } 139 140 func (s *SQLCommon) GetOperationByID(ctx context.Context, id *fftypes.UUID) (operation *fftypes.Operation, err error) { 141 142 rows, err := s.query(ctx, 143 sq.Select(opColumns...). 144 From("operations"). 145 Where(sq.Eq{"id": id}), 146 ) 147 if err != nil { 148 return nil, err 149 } 150 defer rows.Close() 151 152 if !rows.Next() { 153 log.L(ctx).Debugf("Operation '%s' not found", id) 154 return nil, nil 155 } 156 157 op, err := s.opResult(ctx, rows) 158 if err != nil { 159 return nil, err 160 } 161 162 return op, nil 163 } 164 165 func (s *SQLCommon) GetOperations(ctx context.Context, filter database.Filter) (operation []*fftypes.Operation, err error) { 166 167 query, err := s.filterSelect(ctx, "", sq.Select(opColumns...).From("operations"), filter, opFilterTypeMap) 168 if err != nil { 169 return nil, err 170 } 171 172 rows, err := s.query(ctx, query) 173 if err != nil { 174 return nil, err 175 } 176 defer rows.Close() 177 178 ops := []*fftypes.Operation{} 179 for rows.Next() { 180 op, err := s.opResult(ctx, rows) 181 if err != nil { 182 return nil, err 183 } 184 ops = append(ops, op) 185 } 186 187 return ops, err 188 } 189 190 func (s *SQLCommon) UpdateOperation(ctx context.Context, id *fftypes.UUID, update database.Update) (err error) { 191 192 ctx, tx, autoCommit, err := s.beginOrUseTx(ctx) 193 if err != nil { 194 return err 195 } 196 defer s.rollbackTx(ctx, tx, autoCommit) 197 198 query, err := s.buildUpdate(sq.Update("operations"), update, opFilterTypeMap) 199 if err != nil { 200 return err 201 } 202 query = query.Set("updated", fftypes.Now()) 203 query = query.Where(sq.Eq{"id": id}) 204 205 err = s.updateTx(ctx, tx, query) 206 if err != nil { 207 return err 208 } 209 210 return s.commitTx(ctx, tx, autoCommit) 211 }