github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/pin_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  	pinColumns = []string{
    32  		"masked",
    33  		"hash",
    34  		"batch_id",
    35  		"idx",
    36  		"dispatched",
    37  		"created",
    38  	}
    39  	pinFilterTypeMap = map[string]string{
    40  		"batch": "batch_id",
    41  		"index": "idx",
    42  	}
    43  )
    44  
    45  func (s *SQLCommon) UpsertPin(ctx context.Context, pin *fftypes.Pin) (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  	// Do a select within the transaction to detemine if the UUID already exists
    53  	pinRows, err := s.queryTx(ctx, tx,
    54  		sq.Select(s.provider.SequenceField(""), "masked", "dispatched").
    55  			From("pins").
    56  			Where(sq.Eq{
    57  				"hash":     pin.Hash,
    58  				"batch_id": pin.Batch,
    59  				"idx":      pin.Index,
    60  			}))
    61  	if err != nil {
    62  		return err
    63  	}
    64  	existing := pinRows.Next()
    65  
    66  	if existing {
    67  		err := pinRows.Scan(&pin.Sequence, &pin.Masked, &pin.Dispatched)
    68  		pinRows.Close()
    69  		if err != nil {
    70  			return i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "pins")
    71  		}
    72  		// Pin's can only go from undispatched, to dispatched - so no update here.
    73  		log.L(ctx).Debugf("Existing pin returned at sequence %d", pin.Sequence)
    74  	} else {
    75  		pinRows.Close()
    76  		if pin.Sequence, err = s.insertTx(ctx, tx,
    77  			sq.Insert("pins").
    78  				Columns(pinColumns...).
    79  				Values(
    80  					pin.Masked,
    81  					pin.Hash,
    82  					pin.Batch,
    83  					pin.Index,
    84  					pin.Dispatched,
    85  					pin.Created,
    86  				),
    87  		); err != nil {
    88  			return err
    89  		}
    90  
    91  		s.postCommitEvent(tx, func() {
    92  			s.callbacks.PinCreated(pin.Sequence)
    93  		})
    94  
    95  	}
    96  
    97  	return s.commitTx(ctx, tx, autoCommit)
    98  }
    99  
   100  func (s *SQLCommon) pinResult(ctx context.Context, row *sql.Rows) (*fftypes.Pin, error) {
   101  	pin := fftypes.Pin{}
   102  	err := row.Scan(
   103  		&pin.Masked,
   104  		&pin.Hash,
   105  		&pin.Batch,
   106  		&pin.Index,
   107  		&pin.Dispatched,
   108  		&pin.Created,
   109  		&pin.Sequence,
   110  	)
   111  	if err != nil {
   112  		return nil, i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "pins")
   113  	}
   114  	return &pin, nil
   115  }
   116  
   117  func (s *SQLCommon) GetPins(ctx context.Context, filter database.Filter) (message []*fftypes.Pin, err error) {
   118  
   119  	cols := append([]string{}, pinColumns...)
   120  	cols = append(cols, s.provider.SequenceField(""))
   121  	query, err := s.filterSelect(ctx, "", sq.Select(cols...).From("pins"), filter, pinFilterTypeMap)
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  
   126  	rows, err := s.query(ctx, query)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  	defer rows.Close()
   131  
   132  	pin := []*fftypes.Pin{}
   133  	for rows.Next() {
   134  		d, err := s.pinResult(ctx, rows)
   135  		if err != nil {
   136  			return nil, err
   137  		}
   138  		pin = append(pin, d)
   139  	}
   140  
   141  	return pin, err
   142  
   143  }
   144  
   145  func (s *SQLCommon) SetPinDispatched(ctx context.Context, sequence int64) (err error) {
   146  
   147  	ctx, tx, autoCommit, err := s.beginOrUseTx(ctx)
   148  	if err != nil {
   149  		return err
   150  	}
   151  	defer s.rollbackTx(ctx, tx, autoCommit)
   152  
   153  	err = s.updateTx(ctx, tx, sq.
   154  		Update("pins").
   155  		Set("dispatched", true).
   156  		Where(sq.Eq{
   157  			s.provider.SequenceField(""): sequence,
   158  		}))
   159  	if err != nil {
   160  		return err
   161  	}
   162  
   163  	return s.commitTx(ctx, tx, autoCommit)
   164  }
   165  
   166  func (s *SQLCommon) DeletePin(ctx context.Context, sequence int64) (err error) {
   167  
   168  	ctx, tx, autoCommit, err := s.beginOrUseTx(ctx)
   169  	if err != nil {
   170  		return err
   171  	}
   172  	defer s.rollbackTx(ctx, tx, autoCommit)
   173  
   174  	err = s.deleteTx(ctx, tx, sq.Delete("pins").Where(sq.Eq{
   175  		s.provider.SequenceField(""): sequence,
   176  	}))
   177  	if err != nil {
   178  		return err
   179  	}
   180  
   181  	return s.commitTx(ctx, tx, autoCommit)
   182  }