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  }