github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/namespace_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  	namespaceColumns = []string{
    32  		"id",
    33  		"message_id",
    34  		"ntype",
    35  		"name",
    36  		"description",
    37  		"created",
    38  	}
    39  	namespaceFilterTypeMap = map[string]string{
    40  		"message": "message_id",
    41  		"type":    "ntype",
    42  	}
    43  )
    44  
    45  func (s *SQLCommon) UpsertNamespace(ctx context.Context, namespace *fftypes.Namespace, allowExisting bool) (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  	existing := false
    53  	if allowExisting {
    54  		// Do a select within the transaction to detemine if the UUID already exists
    55  		namespaceRows, err := s.queryTx(ctx, tx,
    56  			sq.Select("id").
    57  				From("namespaces").
    58  				Where(sq.Eq{"name": namespace.Name}),
    59  		)
    60  		if err != nil {
    61  			return err
    62  		}
    63  		existing = namespaceRows.Next()
    64  
    65  		if existing {
    66  			var id fftypes.UUID
    67  			_ = namespaceRows.Scan(&id)
    68  			if namespace.ID != nil {
    69  				if *namespace.ID != id {
    70  					namespaceRows.Close()
    71  					return database.IDMismatch
    72  				}
    73  			}
    74  			namespace.ID = &id // Update on returned object
    75  		}
    76  		namespaceRows.Close()
    77  	}
    78  
    79  	if existing {
    80  		// Update the namespace
    81  		if err = s.updateTx(ctx, tx,
    82  			sq.Update("namespaces").
    83  				// Note we do not update ID
    84  				Set("message_id", namespace.Message).
    85  				Set("ntype", string(namespace.Type)).
    86  				Set("name", namespace.Name).
    87  				Set("description", namespace.Description).
    88  				Set("created", namespace.Created).
    89  				Where(sq.Eq{"name": namespace.Name}),
    90  		); err != nil {
    91  			return err
    92  		}
    93  	} else {
    94  		if namespace.ID == nil {
    95  			namespace.ID = fftypes.NewUUID()
    96  		}
    97  
    98  		if _, err = s.insertTx(ctx, tx,
    99  			sq.Insert("namespaces").
   100  				Columns(namespaceColumns...).
   101  				Values(
   102  					namespace.ID,
   103  					namespace.Message,
   104  					string(namespace.Type),
   105  					namespace.Name,
   106  					namespace.Description,
   107  					namespace.Created,
   108  				),
   109  		); err != nil {
   110  			return err
   111  		}
   112  	}
   113  
   114  	return s.commitTx(ctx, tx, autoCommit)
   115  }
   116  
   117  func (s *SQLCommon) namespaceResult(ctx context.Context, row *sql.Rows) (*fftypes.Namespace, error) {
   118  	namespace := fftypes.Namespace{}
   119  	err := row.Scan(
   120  		&namespace.ID,
   121  		&namespace.Message,
   122  		&namespace.Type,
   123  		&namespace.Name,
   124  		&namespace.Description,
   125  		&namespace.Created,
   126  	)
   127  	if err != nil {
   128  		return nil, i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "namespaces")
   129  	}
   130  	return &namespace, nil
   131  }
   132  
   133  func (s *SQLCommon) GetNamespace(ctx context.Context, name string) (message *fftypes.Namespace, err error) {
   134  
   135  	rows, err := s.query(ctx,
   136  		sq.Select(namespaceColumns...).
   137  			From("namespaces").
   138  			Where(sq.Eq{"name": name}),
   139  	)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  	defer rows.Close()
   144  
   145  	if !rows.Next() {
   146  		log.L(ctx).Debugf("Namespace '%s' not found", name)
   147  		return nil, nil
   148  	}
   149  
   150  	namespace, err := s.namespaceResult(ctx, rows)
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  
   155  	return namespace, nil
   156  }
   157  
   158  func (s *SQLCommon) GetNamespaces(ctx context.Context, filter database.Filter) (message []*fftypes.Namespace, err error) {
   159  
   160  	query, err := s.filterSelect(ctx, "", sq.Select(namespaceColumns...).From("namespaces"), filter, namespaceFilterTypeMap)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	rows, err := s.query(ctx, query)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  	defer rows.Close()
   170  
   171  	namespace := []*fftypes.Namespace{}
   172  	for rows.Next() {
   173  		d, err := s.namespaceResult(ctx, rows)
   174  		if err != nil {
   175  			return nil, err
   176  		}
   177  		namespace = append(namespace, d)
   178  	}
   179  
   180  	return namespace, err
   181  
   182  }
   183  
   184  func (s *SQLCommon) UpdateNamespace(ctx context.Context, id *fftypes.UUID, update database.Update) (err error) {
   185  
   186  	ctx, tx, autoCommit, err := s.beginOrUseTx(ctx)
   187  	if err != nil {
   188  		return err
   189  	}
   190  	defer s.rollbackTx(ctx, tx, autoCommit)
   191  
   192  	query, err := s.buildUpdate(sq.Update("namespaces"), update, namespaceFilterTypeMap)
   193  	if err != nil {
   194  		return err
   195  	}
   196  	query = query.Where(sq.Eq{"id": id})
   197  
   198  	err = s.updateTx(ctx, tx, query)
   199  	if err != nil {
   200  		return err
   201  	}
   202  
   203  	return s.commitTx(ctx, tx, autoCommit)
   204  }
   205  
   206  func (s *SQLCommon) DeleteNamespace(ctx context.Context, id *fftypes.UUID) (err error) {
   207  
   208  	ctx, tx, autoCommit, err := s.beginOrUseTx(ctx)
   209  	if err != nil {
   210  		return err
   211  	}
   212  	defer s.rollbackTx(ctx, tx, autoCommit)
   213  
   214  	err = s.deleteTx(ctx, tx, sq.Delete("namespaces").Where(sq.Eq{
   215  		"id": id,
   216  	}))
   217  	if err != nil {
   218  		return err
   219  	}
   220  
   221  	return s.commitTx(ctx, tx, autoCommit)
   222  }