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  }