github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/pkg/database/query_fields.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 database
    18  
    19  import (
    20  	"context"
    21  	"database/sql"
    22  	"database/sql/driver"
    23  	"encoding/json"
    24  	"fmt"
    25  	"reflect"
    26  	"strconv"
    27  	"strings"
    28  
    29  	"github.com/kaleido-io/firefly/internal/i18n"
    30  	"github.com/kaleido-io/firefly/pkg/fftypes"
    31  )
    32  
    33  // QueryFactory creates a filter builder in the given context, and contains the rules on
    34  // which fields can be used by the builder (and how they are serialized)
    35  type QueryFactory interface {
    36  	NewFilter(ctx context.Context) FilterBuilder
    37  	NewFilterLimit(ctx context.Context, defLimit uint64) FilterBuilder
    38  	NewUpdate(ctx context.Context) UpdateBuilder
    39  }
    40  
    41  type queryFields map[string]Field
    42  
    43  func (qf *queryFields) NewFilterLimit(ctx context.Context, defLimit uint64) FilterBuilder {
    44  	return &filterBuilder{
    45  		ctx:         ctx,
    46  		queryFields: *qf,
    47  		limit:       defLimit,
    48  	}
    49  }
    50  
    51  func (qf *queryFields) NewFilter(ctx context.Context) FilterBuilder {
    52  	return qf.NewFilterLimit(ctx, 0)
    53  }
    54  
    55  func (qf *queryFields) NewUpdate(ctx context.Context) UpdateBuilder {
    56  	return &updateBuilder{
    57  		ctx:         ctx,
    58  		queryFields: *qf,
    59  	}
    60  }
    61  
    62  // FieldSerialization - we stand on the shoulders of the well adopted SQL serialization interface here to help us define what
    63  // string<->value looks like, even though this plugin interface is not tightly coupled to SQL.
    64  type FieldSerialization interface {
    65  	driver.Valuer
    66  	sql.Scanner // Implementations can assume the value is ALWAYS a string
    67  }
    68  
    69  type Field interface {
    70  	getSerialization() FieldSerialization
    71  }
    72  
    73  type StringField struct{}
    74  type stringField struct{ s string }
    75  
    76  func (f *stringField) Scan(src interface{}) error {
    77  	switch tv := src.(type) {
    78  	case string:
    79  		f.s = tv
    80  	case int:
    81  		f.s = strconv.FormatInt(int64(tv), 10)
    82  	case int32:
    83  		f.s = strconv.FormatInt(int64(tv), 10)
    84  	case int64:
    85  		f.s = strconv.FormatInt(tv, 10)
    86  	case uint:
    87  		f.s = strconv.FormatInt(int64(tv), 10)
    88  	case uint32:
    89  		f.s = strconv.FormatInt(int64(tv), 10)
    90  	case uint64:
    91  		f.s = strconv.FormatInt(int64(tv), 10)
    92  	case *fftypes.UUID:
    93  		if tv != nil {
    94  			f.s = tv.String()
    95  		}
    96  	case fftypes.UUID:
    97  		f.s = tv.String()
    98  	case *fftypes.Bytes32:
    99  		if tv != nil {
   100  			f.s = tv.String()
   101  		}
   102  	case fftypes.Bytes32:
   103  		f.s = tv.String()
   104  	case nil:
   105  	default:
   106  		if reflect.TypeOf(tv).Kind() == reflect.String {
   107  			// This is helpful for status enums
   108  			f.s = reflect.ValueOf(tv).String()
   109  		} else {
   110  			return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, f.s)
   111  		}
   112  	}
   113  	return nil
   114  }
   115  func (f *stringField) Value() (driver.Value, error)         { return f.s, nil }
   116  func (f *stringField) String() string                       { return f.s }
   117  func (f *StringField) getSerialization() FieldSerialization { return &stringField{} }
   118  
   119  type UUIDField struct{}
   120  type uuidField struct{ u *fftypes.UUID }
   121  
   122  func (f *uuidField) Scan(src interface{}) (err error) {
   123  	switch tv := src.(type) {
   124  	case string:
   125  		if tv == "" {
   126  			f.u = nil
   127  			return nil
   128  		}
   129  		f.u, err = fftypes.ParseUUID(context.Background(), tv)
   130  		return err
   131  	case *fftypes.UUID:
   132  		f.u = tv
   133  	case fftypes.UUID:
   134  		u := tv
   135  		f.u = &u
   136  	case *fftypes.Bytes32:
   137  		if tv == nil {
   138  			f.u = nil
   139  			return nil
   140  		}
   141  		var u fftypes.UUID
   142  		copy(u[:], tv[0:16])
   143  		f.u = &u
   144  	case fftypes.Bytes32:
   145  		var u fftypes.UUID
   146  		copy(u[:], tv[0:16])
   147  		f.u = &u
   148  	case nil:
   149  	default:
   150  		return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, f.u)
   151  	}
   152  	return nil
   153  }
   154  func (f *uuidField) Value() (driver.Value, error)         { return f.u.Value() }
   155  func (f *uuidField) String() string                       { return fmt.Sprintf("%v", f.u) }
   156  func (f *UUIDField) getSerialization() FieldSerialization { return &uuidField{} }
   157  
   158  type Int64Field struct{}
   159  type int64Field struct{ i int64 }
   160  
   161  func (f *int64Field) Scan(src interface{}) (err error) {
   162  	switch tv := src.(type) {
   163  	case int:
   164  		f.i = int64(tv)
   165  	case int32:
   166  		f.i = int64(tv)
   167  	case int64:
   168  		f.i = tv
   169  	case uint:
   170  		f.i = int64(tv)
   171  	case uint32:
   172  		f.i = int64(tv)
   173  	case uint64:
   174  		f.i = int64(tv)
   175  	case string:
   176  		f.i, err = strconv.ParseInt(src.(string), 10, 64)
   177  		if err != nil {
   178  			return i18n.WrapError(context.Background(), err, i18n.MsgScanFailed, src, int64(0))
   179  		}
   180  	default:
   181  		return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, f.i)
   182  	}
   183  	return nil
   184  }
   185  func (f *int64Field) Value() (driver.Value, error)         { return f.i, nil }
   186  func (f *int64Field) String() string                       { return fmt.Sprintf("%d", f.i) }
   187  func (f *Int64Field) getSerialization() FieldSerialization { return &int64Field{} }
   188  
   189  type TimeField struct{}
   190  type timeField struct{ t *fftypes.FFTime }
   191  
   192  func (f *timeField) Scan(src interface{}) (err error) {
   193  	switch tv := src.(type) {
   194  	case int:
   195  		f.t = fftypes.UnixTime(int64(tv))
   196  	case int64:
   197  		f.t = fftypes.UnixTime(tv)
   198  	case string:
   199  		f.t, err = fftypes.ParseString(tv)
   200  		return err
   201  	case fftypes.FFTime:
   202  		f.t = &tv
   203  		return nil
   204  	case *fftypes.FFTime:
   205  		f.t = tv
   206  		return nil
   207  	case nil:
   208  		f.t = nil
   209  		return nil
   210  	default:
   211  		return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, f.t)
   212  	}
   213  	return nil
   214  }
   215  func (f *timeField) Value() (driver.Value, error) {
   216  	if f.t == nil {
   217  		return nil, nil
   218  	}
   219  	return f.t.UnixNano(), nil
   220  }
   221  func (f *timeField) String() string                       { return fmt.Sprintf("%v", f.t) }
   222  func (f *TimeField) getSerialization() FieldSerialization { return &timeField{} }
   223  
   224  type JSONField struct{}
   225  type jsonField struct{ b []byte }
   226  
   227  func (f *jsonField) Scan(src interface{}) (err error) {
   228  	switch tv := src.(type) {
   229  	case string:
   230  		f.b = []byte(tv)
   231  	case []byte:
   232  		f.b = tv
   233  	case fftypes.JSONObject:
   234  		f.b, err = json.Marshal(tv)
   235  	case nil:
   236  		f.b = nil
   237  	default:
   238  		return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, f.b)
   239  	}
   240  	return err
   241  }
   242  func (f *jsonField) Value() (driver.Value, error)         { return f.b, nil }
   243  func (f *jsonField) String() string                       { return fmt.Sprintf("%s", f.b) }
   244  func (f *JSONField) getSerialization() FieldSerialization { return &jsonField{} }
   245  
   246  type FFNameArrayField struct{}
   247  type ffNameArrayField struct{ na fftypes.FFNameArray }
   248  
   249  func (f *ffNameArrayField) Scan(src interface{}) (err error) {
   250  	return f.na.Scan(src)
   251  }
   252  func (f *ffNameArrayField) Value() (driver.Value, error)         { return f.na.String(), nil }
   253  func (f *ffNameArrayField) String() string                       { return f.na.String() }
   254  func (f *FFNameArrayField) getSerialization() FieldSerialization { return &ffNameArrayField{} }
   255  
   256  type BoolField struct{}
   257  type boolField struct{ b bool }
   258  
   259  func (f *boolField) Scan(src interface{}) (err error) {
   260  	switch tv := src.(type) {
   261  	case int:
   262  		f.b = tv != 0
   263  	case int32:
   264  		f.b = tv != 0
   265  	case int64:
   266  		f.b = tv != 0
   267  	case uint:
   268  		f.b = tv != 0
   269  	case uint32:
   270  		f.b = tv != 0
   271  	case uint64:
   272  		f.b = tv != 0
   273  	case bool:
   274  		f.b = tv
   275  	case string:
   276  		f.b = strings.EqualFold(tv, "true")
   277  	case nil:
   278  		f.b = false
   279  	default:
   280  		return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, f.b)
   281  	}
   282  	return nil
   283  }
   284  func (f *boolField) Value() (driver.Value, error)         { return f.b, nil }
   285  func (f *boolField) String() string                       { return fmt.Sprintf("%t", f.b) }
   286  func (f *BoolField) getSerialization() FieldSerialization { return &boolField{} }