github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/namespace_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 namespaceColumns = []string{ 32 "id", 33 "message_id", 34 "ntype", 35 "name", 36 "description", 37 "created", 38 } 39 namespaceFilterTypeMap = map[string]string{ 40 "message": "message_id", 41 "type": "ntype", 42 } 43 ) 44 45 func (s *SQLCommon) UpsertNamespace(ctx context.Context, namespace *fftypes.Namespace, allowExisting bool) (err error) { 46 ctx, tx, autoCommit, err := s.beginOrUseTx(ctx) 47 if err != nil { 48 return err 49 } 50 defer s.rollbackTx(ctx, tx, autoCommit) 51 52 existing := false 53 if allowExisting { 54 // Do a select within the transaction to detemine if the UUID already exists 55 namespaceRows, err := s.queryTx(ctx, tx, 56 sq.Select("id"). 57 From("namespaces"). 58 Where(sq.Eq{"name": namespace.Name}), 59 ) 60 if err != nil { 61 return err 62 } 63 existing = namespaceRows.Next() 64 65 if existing { 66 var id fftypes.UUID 67 _ = namespaceRows.Scan(&id) 68 if namespace.ID != nil { 69 if *namespace.ID != id { 70 namespaceRows.Close() 71 return database.IDMismatch 72 } 73 } 74 namespace.ID = &id // Update on returned object 75 } 76 namespaceRows.Close() 77 } 78 79 if existing { 80 // Update the namespace 81 if err = s.updateTx(ctx, tx, 82 sq.Update("namespaces"). 83 // Note we do not update ID 84 Set("message_id", namespace.Message). 85 Set("ntype", string(namespace.Type)). 86 Set("name", namespace.Name). 87 Set("description", namespace.Description). 88 Set("created", namespace.Created). 89 Where(sq.Eq{"name": namespace.Name}), 90 ); err != nil { 91 return err 92 } 93 } else { 94 if namespace.ID == nil { 95 namespace.ID = fftypes.NewUUID() 96 } 97 98 if _, err = s.insertTx(ctx, tx, 99 sq.Insert("namespaces"). 100 Columns(namespaceColumns...). 101 Values( 102 namespace.ID, 103 namespace.Message, 104 string(namespace.Type), 105 namespace.Name, 106 namespace.Description, 107 namespace.Created, 108 ), 109 ); err != nil { 110 return err 111 } 112 } 113 114 return s.commitTx(ctx, tx, autoCommit) 115 } 116 117 func (s *SQLCommon) namespaceResult(ctx context.Context, row *sql.Rows) (*fftypes.Namespace, error) { 118 namespace := fftypes.Namespace{} 119 err := row.Scan( 120 &namespace.ID, 121 &namespace.Message, 122 &namespace.Type, 123 &namespace.Name, 124 &namespace.Description, 125 &namespace.Created, 126 ) 127 if err != nil { 128 return nil, i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "namespaces") 129 } 130 return &namespace, nil 131 } 132 133 func (s *SQLCommon) GetNamespace(ctx context.Context, name string) (message *fftypes.Namespace, err error) { 134 135 rows, err := s.query(ctx, 136 sq.Select(namespaceColumns...). 137 From("namespaces"). 138 Where(sq.Eq{"name": name}), 139 ) 140 if err != nil { 141 return nil, err 142 } 143 defer rows.Close() 144 145 if !rows.Next() { 146 log.L(ctx).Debugf("Namespace '%s' not found", name) 147 return nil, nil 148 } 149 150 namespace, err := s.namespaceResult(ctx, rows) 151 if err != nil { 152 return nil, err 153 } 154 155 return namespace, nil 156 } 157 158 func (s *SQLCommon) GetNamespaces(ctx context.Context, filter database.Filter) (message []*fftypes.Namespace, err error) { 159 160 query, err := s.filterSelect(ctx, "", sq.Select(namespaceColumns...).From("namespaces"), filter, namespaceFilterTypeMap) 161 if err != nil { 162 return nil, err 163 } 164 165 rows, err := s.query(ctx, query) 166 if err != nil { 167 return nil, err 168 } 169 defer rows.Close() 170 171 namespace := []*fftypes.Namespace{} 172 for rows.Next() { 173 d, err := s.namespaceResult(ctx, rows) 174 if err != nil { 175 return nil, err 176 } 177 namespace = append(namespace, d) 178 } 179 180 return namespace, err 181 182 } 183 184 func (s *SQLCommon) UpdateNamespace(ctx context.Context, id *fftypes.UUID, update database.Update) (err error) { 185 186 ctx, tx, autoCommit, err := s.beginOrUseTx(ctx) 187 if err != nil { 188 return err 189 } 190 defer s.rollbackTx(ctx, tx, autoCommit) 191 192 query, err := s.buildUpdate(sq.Update("namespaces"), update, namespaceFilterTypeMap) 193 if err != nil { 194 return err 195 } 196 query = query.Where(sq.Eq{"id": id}) 197 198 err = s.updateTx(ctx, tx, query) 199 if err != nil { 200 return err 201 } 202 203 return s.commitTx(ctx, tx, autoCommit) 204 } 205 206 func (s *SQLCommon) DeleteNamespace(ctx context.Context, id *fftypes.UUID) (err error) { 207 208 ctx, tx, autoCommit, err := s.beginOrUseTx(ctx) 209 if err != nil { 210 return err 211 } 212 defer s.rollbackTx(ctx, tx, autoCommit) 213 214 err = s.deleteTx(ctx, tx, sq.Delete("namespaces").Where(sq.Eq{ 215 "id": id, 216 })) 217 if err != nil { 218 return err 219 } 220 221 return s.commitTx(ctx, tx, autoCommit) 222 }