github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/orchestrator/data_query.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 orchestrator 18 19 import ( 20 "context" 21 "database/sql/driver" 22 23 "github.com/kaleido-io/firefly/internal/i18n" 24 "github.com/kaleido-io/firefly/pkg/database" 25 "github.com/kaleido-io/firefly/pkg/fftypes" 26 ) 27 28 func (or *orchestrator) verifyNamespaceSyntax(ctx context.Context, ns string) error { 29 return fftypes.ValidateFFNameField(ctx, ns, "namespace") 30 } 31 32 func (or *orchestrator) verifyIDAndNamespace(ctx context.Context, ns, id string) (*fftypes.UUID, error) { 33 u, err := fftypes.ParseUUID(ctx, id) 34 if err != nil { 35 return nil, err 36 } 37 err = or.verifyNamespaceSyntax(ctx, ns) 38 return u, err 39 } 40 41 func (or *orchestrator) GetNamespace(ctx context.Context, ns string) (*fftypes.Namespace, error) { 42 return or.database.GetNamespace(ctx, ns) 43 } 44 45 func (or *orchestrator) GetTransactionByID(ctx context.Context, ns, id string) (*fftypes.Transaction, error) { 46 u, err := or.verifyIDAndNamespace(ctx, ns, id) 47 if err != nil { 48 return nil, err 49 } 50 return or.database.GetTransactionByID(ctx, u) 51 } 52 53 func (or *orchestrator) GetTransactionOperations(ctx context.Context, ns, id string) ([]*fftypes.Operation, error) { 54 u, err := or.verifyIDAndNamespace(ctx, ns, id) 55 if err != nil { 56 return nil, err 57 } 58 fb := database.OperationQueryFactory.NewFilter(ctx) 59 filter := fb.And( 60 fb.Eq("tx", u), 61 fb.Eq("namespace", ns), 62 ) 63 return or.database.GetOperations(ctx, filter) 64 } 65 66 func (or *orchestrator) getMessageByID(ctx context.Context, ns, id string) (*fftypes.Message, error) { 67 u, err := or.verifyIDAndNamespace(ctx, ns, id) 68 if err != nil { 69 return nil, err 70 } 71 msg, err := or.database.GetMessageByID(ctx, u) 72 if err == nil && msg == nil { 73 return nil, i18n.NewError(ctx, i18n.Msg404NotFound) 74 } 75 return msg, err 76 } 77 78 func (or *orchestrator) GetMessageByID(ctx context.Context, ns, id string, withValues bool) (*fftypes.MessageInput, error) { 79 msg, err := or.getMessageByID(ctx, ns, id) 80 if err != nil { 81 return nil, err 82 } 83 msgI := &fftypes.MessageInput{ 84 Message: *msg, 85 } 86 if withValues { 87 // Lookup the full data 88 data, _, err := or.data.GetMessageData(ctx, msg, true) 89 if err != nil { 90 return nil, err 91 } 92 msgI.InputData = make(fftypes.InputData, len(data)) 93 for i, d := range data { 94 msgI.InputData[i] = &fftypes.DataRefOrValue{ 95 DataRef: fftypes.DataRef{ 96 ID: d.ID, 97 Hash: d.Hash, 98 }, 99 Validator: d.Validator, 100 Datatype: d.Datatype, 101 Value: d.Value, 102 } 103 } 104 } else { 105 // Just put the data refs into the serialized struct 106 msgI.InputData = make(fftypes.InputData, len(msg.Data)) 107 for i, dr := range msg.Data { 108 msgI.InputData[i] = &fftypes.DataRefOrValue{ 109 DataRef: *dr, 110 } 111 } 112 } 113 return msgI, err 114 } 115 116 func (or *orchestrator) GetBatchByID(ctx context.Context, ns, id string) (*fftypes.Batch, error) { 117 u, err := or.verifyIDAndNamespace(ctx, ns, id) 118 if err != nil { 119 return nil, err 120 } 121 return or.database.GetBatchByID(ctx, u) 122 } 123 124 func (or *orchestrator) GetDataByID(ctx context.Context, ns, id string) (*fftypes.Data, error) { 125 u, err := or.verifyIDAndNamespace(ctx, ns, id) 126 if err != nil { 127 return nil, err 128 } 129 return or.database.GetDataByID(ctx, u, true) 130 } 131 132 func (or *orchestrator) GetDatatypeByID(ctx context.Context, ns, id string) (*fftypes.Datatype, error) { 133 u, err := or.verifyIDAndNamespace(ctx, ns, id) 134 if err != nil { 135 return nil, err 136 } 137 return or.database.GetDatatypeByID(ctx, u) 138 } 139 140 func (or *orchestrator) GetOperationByID(ctx context.Context, ns, id string) (*fftypes.Operation, error) { 141 u, err := or.verifyIDAndNamespace(ctx, ns, id) 142 if err != nil { 143 return nil, err 144 } 145 return or.database.GetOperationByID(ctx, u) 146 } 147 148 func (or *orchestrator) GetEventByID(ctx context.Context, ns, id string) (*fftypes.Event, error) { 149 u, err := or.verifyIDAndNamespace(ctx, ns, id) 150 if err != nil { 151 return nil, err 152 } 153 return or.database.GetEventByID(ctx, u) 154 } 155 156 func (or *orchestrator) GetNamespaces(ctx context.Context, filter database.AndFilter) ([]*fftypes.Namespace, error) { 157 return or.database.GetNamespaces(ctx, filter) 158 } 159 160 func (or *orchestrator) scopeNS(ns string, filter database.AndFilter) database.AndFilter { 161 return filter.Condition(filter.Builder().Eq("namespace", ns)) 162 } 163 164 func (or *orchestrator) GetTransactions(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Transaction, error) { 165 filter = or.scopeNS(ns, filter) 166 return or.database.GetTransactions(ctx, filter) 167 } 168 169 func (or *orchestrator) GetMessages(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Message, error) { 170 filter = or.scopeNS(ns, filter) 171 return or.database.GetMessages(ctx, filter) 172 } 173 174 func (or *orchestrator) GetMessageData(ctx context.Context, ns, id string) ([]*fftypes.Data, error) { 175 msg, err := or.getMessageByID(ctx, ns, id) 176 if err != nil || msg == nil { 177 return nil, err 178 } 179 data, _, err := or.data.GetMessageData(ctx, msg, true) 180 return data, err 181 } 182 183 func (or *orchestrator) getMessageTransactionID(ctx context.Context, ns, id string) (*fftypes.UUID, error) { 184 msg, err := or.getMessageByID(ctx, ns, id) 185 if err != nil || msg == nil { 186 return nil, err 187 } 188 var txID *fftypes.UUID 189 if msg.Header.TxType == fftypes.TransactionTypeBatchPin { 190 if msg.BatchID == nil { 191 return nil, i18n.NewError(ctx, i18n.MsgBatchNotSet) 192 } 193 batch, err := or.database.GetBatchByID(ctx, msg.BatchID) 194 if err != nil { 195 return nil, err 196 } 197 if batch == nil { 198 return nil, i18n.NewError(ctx, i18n.MsgBatchNotFound, msg.BatchID) 199 } 200 txID = batch.Payload.TX.ID 201 if txID == nil { 202 return nil, i18n.NewError(ctx, i18n.MsgBatchTXNotSet, msg.BatchID) 203 } 204 } else { 205 return nil, i18n.NewError(ctx, i18n.MsgNoTransaction) 206 } 207 return txID, nil 208 } 209 210 func (or *orchestrator) GetMessageTransaction(ctx context.Context, ns, id string) (*fftypes.Transaction, error) { 211 txID, err := or.getMessageTransactionID(ctx, ns, id) 212 if err != nil { 213 return nil, err 214 } 215 return or.database.GetTransactionByID(ctx, txID) 216 } 217 218 func (or *orchestrator) GetMessageOperations(ctx context.Context, ns, id string) ([]*fftypes.Operation, error) { 219 txID, err := or.getMessageTransactionID(ctx, ns, id) 220 if err != nil { 221 return nil, err 222 } 223 filter := database.OperationQueryFactory.NewFilter(ctx).Eq("tx", txID) 224 return or.database.GetOperations(ctx, filter) 225 } 226 227 func (or *orchestrator) GetMessageEvents(ctx context.Context, ns, id string, filter database.AndFilter) ([]*fftypes.Event, error) { 228 msg, err := or.getMessageByID(ctx, ns, id) 229 if err != nil || msg == nil { 230 return nil, err 231 } 232 // Events can refer to the message, or any data in the message 233 // So scope the event down to those referred UUIDs, in addition to any and conditions passed in 234 referencedIDs := make([]driver.Value, len(msg.Data)+1) 235 referencedIDs[0] = msg.Header.ID 236 for i, dataRef := range msg.Data { 237 referencedIDs[i+1] = dataRef.ID 238 } 239 filter = filter.Condition(filter.Builder().In("reference", referencedIDs)) 240 // Execute the filter 241 return or.database.GetEvents(ctx, filter) 242 } 243 244 func (or *orchestrator) GetBatches(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Batch, error) { 245 filter = or.scopeNS(ns, filter) 246 return or.database.GetBatches(ctx, filter) 247 } 248 249 func (or *orchestrator) GetData(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Data, error) { 250 filter = or.scopeNS(ns, filter) 251 return or.database.GetData(ctx, filter) 252 } 253 254 func (or *orchestrator) GetMessagesForData(ctx context.Context, ns, dataID string, filter database.AndFilter) ([]*fftypes.Message, error) { 255 filter = or.scopeNS(ns, filter) 256 u, err := or.verifyIDAndNamespace(ctx, ns, dataID) 257 if err != nil { 258 return nil, err 259 } 260 return or.database.GetMessagesForData(ctx, u, filter) 261 } 262 263 func (or *orchestrator) GetDatatypes(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Datatype, error) { 264 filter = or.scopeNS(ns, filter) 265 return or.database.GetDatatypes(ctx, filter) 266 } 267 268 func (or *orchestrator) GetOperations(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Operation, error) { 269 filter = or.scopeNS(ns, filter) 270 return or.database.GetOperations(ctx, filter) 271 } 272 273 func (or *orchestrator) GetEvents(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Event, error) { 274 filter = or.scopeNS(ns, filter) 275 return or.database.GetEvents(ctx, filter) 276 }