github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/datatype_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 "fmt" 23 24 sq "github.com/Masterminds/squirrel" 25 "github.com/kaleido-io/firefly/internal/i18n" 26 "github.com/kaleido-io/firefly/internal/log" 27 "github.com/kaleido-io/firefly/pkg/database" 28 "github.com/kaleido-io/firefly/pkg/fftypes" 29 ) 30 31 var ( 32 datatypeColumns = []string{ 33 "id", 34 "message_id", 35 "validator", 36 "namespace", 37 "name", 38 "version", 39 "hash", 40 "created", 41 "value", 42 } 43 datatypeFilterTypeMap = map[string]string{ 44 "message": "message_id", 45 } 46 ) 47 48 func (s *SQLCommon) UpsertDatatype(ctx context.Context, datatype *fftypes.Datatype, allowExisting bool) (err error) { 49 ctx, tx, autoCommit, err := s.beginOrUseTx(ctx) 50 if err != nil { 51 return err 52 } 53 defer s.rollbackTx(ctx, tx, autoCommit) 54 55 existing := false 56 if allowExisting { 57 // Do a select within the transaction to detemine if the UUID already exists 58 datatypeRows, err := s.queryTx(ctx, tx, 59 sq.Select("id"). 60 From("datatypes"). 61 Where(sq.Eq{"id": datatype.ID}), 62 ) 63 if err != nil { 64 return err 65 } 66 existing = datatypeRows.Next() 67 datatypeRows.Close() 68 } 69 70 if existing { 71 72 // Update the datatype 73 if err = s.updateTx(ctx, tx, 74 sq.Update("datatypes"). 75 Set("message_id", datatype.Message). 76 Set("validator", string(datatype.Validator)). 77 Set("namespace", datatype.Namespace). 78 Set("name", datatype.Name). 79 Set("version", datatype.Version). 80 Set("hash", datatype.Hash). 81 Set("created", datatype.Created). 82 Set("value", datatype.Value). 83 Where(sq.Eq{"id": datatype.ID}), 84 ); err != nil { 85 return err 86 } 87 } else { 88 if _, err = s.insertTx(ctx, tx, 89 sq.Insert("datatypes"). 90 Columns(datatypeColumns...). 91 Values( 92 datatype.ID, 93 datatype.Message, 94 string(datatype.Validator), 95 datatype.Namespace, 96 datatype.Name, 97 datatype.Version, 98 datatype.Hash, 99 datatype.Created, 100 datatype.Value, 101 ), 102 ); err != nil { 103 return err 104 } 105 } 106 107 return s.commitTx(ctx, tx, autoCommit) 108 } 109 110 func (s *SQLCommon) datatypeResult(ctx context.Context, row *sql.Rows) (*fftypes.Datatype, error) { 111 var datatype fftypes.Datatype 112 err := row.Scan( 113 &datatype.ID, 114 &datatype.Message, 115 &datatype.Validator, 116 &datatype.Namespace, 117 &datatype.Name, 118 &datatype.Version, 119 &datatype.Hash, 120 &datatype.Created, 121 &datatype.Value, 122 ) 123 if err != nil { 124 return nil, i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "datatypes") 125 } 126 return &datatype, nil 127 } 128 129 func (s *SQLCommon) getDatatypeEq(ctx context.Context, eq sq.Eq, textName string) (message *fftypes.Datatype, err error) { 130 131 rows, err := s.query(ctx, 132 sq.Select(datatypeColumns...). 133 From("datatypes"). 134 Where(eq), 135 ) 136 if err != nil { 137 return nil, err 138 } 139 defer rows.Close() 140 141 if !rows.Next() { 142 log.L(ctx).Debugf("Datatype '%s' not found", textName) 143 return nil, nil 144 } 145 146 datatype, err := s.datatypeResult(ctx, rows) 147 if err != nil { 148 return nil, err 149 } 150 151 return datatype, nil 152 } 153 154 func (s *SQLCommon) GetDatatypeByID(ctx context.Context, id *fftypes.UUID) (message *fftypes.Datatype, err error) { 155 return s.getDatatypeEq(ctx, sq.Eq{"id": id}, id.String()) 156 } 157 158 func (s *SQLCommon) GetDatatypeByName(ctx context.Context, ns, name, version string) (message *fftypes.Datatype, err error) { 159 return s.getDatatypeEq(ctx, sq.Eq{"namespace": ns, "name": name, "version": version}, fmt.Sprintf("%s:%s", ns, name)) 160 } 161 162 func (s *SQLCommon) GetDatatypes(ctx context.Context, filter database.Filter) (message []*fftypes.Datatype, err error) { 163 164 query, err := s.filterSelect(ctx, "", sq.Select(datatypeColumns...).From("datatypes"), filter, datatypeFilterTypeMap) 165 if err != nil { 166 return nil, err 167 } 168 169 rows, err := s.query(ctx, query) 170 if err != nil { 171 return nil, err 172 } 173 defer rows.Close() 174 175 datatypes := []*fftypes.Datatype{} 176 for rows.Next() { 177 datatype, err := s.datatypeResult(ctx, rows) 178 if err != nil { 179 return nil, err 180 } 181 datatypes = append(datatypes, datatype) 182 } 183 184 return datatypes, err 185 186 } 187 188 func (s *SQLCommon) UpdateDatatype(ctx context.Context, id *fftypes.UUID, update database.Update) (err error) { 189 190 ctx, tx, autoCommit, err := s.beginOrUseTx(ctx) 191 if err != nil { 192 return err 193 } 194 defer s.rollbackTx(ctx, tx, autoCommit) 195 196 query, err := s.buildUpdate(sq.Update("datatypes"), update, datatypeFilterTypeMap) 197 if err != nil { 198 return err 199 } 200 query = query.Where(sq.Eq{"id": id}) 201 202 err = s.updateTx(ctx, tx, query) 203 if err != nil { 204 return err 205 } 206 207 return s.commitTx(ctx, tx, autoCommit) 208 }