github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/datatype_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  	"fmt"
    23  
    24  	sq "github.com/Masterminds/squirrel"
    25  	"github.com/kaleido-io/firefly/internal/i18n"
    26  	"github.com/kaleido-io/firefly/internal/log"
    27  	"github.com/kaleido-io/firefly/pkg/database"
    28  	"github.com/kaleido-io/firefly/pkg/fftypes"
    29  )
    30  
    31  var (
    32  	datatypeColumns = []string{
    33  		"id",
    34  		"message_id",
    35  		"validator",
    36  		"namespace",
    37  		"name",
    38  		"version",
    39  		"hash",
    40  		"created",
    41  		"value",
    42  	}
    43  	datatypeFilterTypeMap = map[string]string{
    44  		"message": "message_id",
    45  	}
    46  )
    47  
    48  func (s *SQLCommon) UpsertDatatype(ctx context.Context, datatype *fftypes.Datatype, allowExisting bool) (err error) {
    49  	ctx, tx, autoCommit, err := s.beginOrUseTx(ctx)
    50  	if err != nil {
    51  		return err
    52  	}
    53  	defer s.rollbackTx(ctx, tx, autoCommit)
    54  
    55  	existing := false
    56  	if allowExisting {
    57  		// Do a select within the transaction to detemine if the UUID already exists
    58  		datatypeRows, err := s.queryTx(ctx, tx,
    59  			sq.Select("id").
    60  				From("datatypes").
    61  				Where(sq.Eq{"id": datatype.ID}),
    62  		)
    63  		if err != nil {
    64  			return err
    65  		}
    66  		existing = datatypeRows.Next()
    67  		datatypeRows.Close()
    68  	}
    69  
    70  	if existing {
    71  
    72  		// Update the datatype
    73  		if err = s.updateTx(ctx, tx,
    74  			sq.Update("datatypes").
    75  				Set("message_id", datatype.Message).
    76  				Set("validator", string(datatype.Validator)).
    77  				Set("namespace", datatype.Namespace).
    78  				Set("name", datatype.Name).
    79  				Set("version", datatype.Version).
    80  				Set("hash", datatype.Hash).
    81  				Set("created", datatype.Created).
    82  				Set("value", datatype.Value).
    83  				Where(sq.Eq{"id": datatype.ID}),
    84  		); err != nil {
    85  			return err
    86  		}
    87  	} else {
    88  		if _, err = s.insertTx(ctx, tx,
    89  			sq.Insert("datatypes").
    90  				Columns(datatypeColumns...).
    91  				Values(
    92  					datatype.ID,
    93  					datatype.Message,
    94  					string(datatype.Validator),
    95  					datatype.Namespace,
    96  					datatype.Name,
    97  					datatype.Version,
    98  					datatype.Hash,
    99  					datatype.Created,
   100  					datatype.Value,
   101  				),
   102  		); err != nil {
   103  			return err
   104  		}
   105  	}
   106  
   107  	return s.commitTx(ctx, tx, autoCommit)
   108  }
   109  
   110  func (s *SQLCommon) datatypeResult(ctx context.Context, row *sql.Rows) (*fftypes.Datatype, error) {
   111  	var datatype fftypes.Datatype
   112  	err := row.Scan(
   113  		&datatype.ID,
   114  		&datatype.Message,
   115  		&datatype.Validator,
   116  		&datatype.Namespace,
   117  		&datatype.Name,
   118  		&datatype.Version,
   119  		&datatype.Hash,
   120  		&datatype.Created,
   121  		&datatype.Value,
   122  	)
   123  	if err != nil {
   124  		return nil, i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "datatypes")
   125  	}
   126  	return &datatype, nil
   127  }
   128  
   129  func (s *SQLCommon) getDatatypeEq(ctx context.Context, eq sq.Eq, textName string) (message *fftypes.Datatype, err error) {
   130  
   131  	rows, err := s.query(ctx,
   132  		sq.Select(datatypeColumns...).
   133  			From("datatypes").
   134  			Where(eq),
   135  	)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	defer rows.Close()
   140  
   141  	if !rows.Next() {
   142  		log.L(ctx).Debugf("Datatype '%s' not found", textName)
   143  		return nil, nil
   144  	}
   145  
   146  	datatype, err := s.datatypeResult(ctx, rows)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  
   151  	return datatype, nil
   152  }
   153  
   154  func (s *SQLCommon) GetDatatypeByID(ctx context.Context, id *fftypes.UUID) (message *fftypes.Datatype, err error) {
   155  	return s.getDatatypeEq(ctx, sq.Eq{"id": id}, id.String())
   156  }
   157  
   158  func (s *SQLCommon) GetDatatypeByName(ctx context.Context, ns, name, version string) (message *fftypes.Datatype, err error) {
   159  	return s.getDatatypeEq(ctx, sq.Eq{"namespace": ns, "name": name, "version": version}, fmt.Sprintf("%s:%s", ns, name))
   160  }
   161  
   162  func (s *SQLCommon) GetDatatypes(ctx context.Context, filter database.Filter) (message []*fftypes.Datatype, err error) {
   163  
   164  	query, err := s.filterSelect(ctx, "", sq.Select(datatypeColumns...).From("datatypes"), filter, datatypeFilterTypeMap)
   165  	if err != nil {
   166  		return nil, err
   167  	}
   168  
   169  	rows, err := s.query(ctx, query)
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  	defer rows.Close()
   174  
   175  	datatypes := []*fftypes.Datatype{}
   176  	for rows.Next() {
   177  		datatype, err := s.datatypeResult(ctx, rows)
   178  		if err != nil {
   179  			return nil, err
   180  		}
   181  		datatypes = append(datatypes, datatype)
   182  	}
   183  
   184  	return datatypes, err
   185  
   186  }
   187  
   188  func (s *SQLCommon) UpdateDatatype(ctx context.Context, id *fftypes.UUID, update database.Update) (err error) {
   189  
   190  	ctx, tx, autoCommit, err := s.beginOrUseTx(ctx)
   191  	if err != nil {
   192  		return err
   193  	}
   194  	defer s.rollbackTx(ctx, tx, autoCommit)
   195  
   196  	query, err := s.buildUpdate(sq.Update("datatypes"), update, datatypeFilterTypeMap)
   197  	if err != nil {
   198  		return err
   199  	}
   200  	query = query.Where(sq.Eq{"id": id})
   201  
   202  	err = s.updateTx(ctx, tx, query)
   203  	if err != nil {
   204  		return err
   205  	}
   206  
   207  	return s.commitTx(ctx, tx, autoCommit)
   208  }