github.com/aacfactory/fns-contrib/databases/sql@v1.2.84/dac/specifications/values.go (about)

     1  package specifications
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	stdsql "database/sql"
     7  	"fmt"
     8  	"github.com/aacfactory/errors"
     9  	"github.com/aacfactory/fns-contrib/databases/sql"
    10  	"github.com/aacfactory/fns/commons/times"
    11  	"github.com/aacfactory/json"
    12  	"reflect"
    13  	"time"
    14  )
    15  
    16  func ScanRows[T any](ctx context.Context, rows sql.Rows, fields []string) (entries []T, err error) {
    17  	spec, specErr := GetSpecification(ctx, Instance[T]())
    18  	if specErr != nil {
    19  		err = specErr
    20  		return
    21  	}
    22  	for rows.Next() {
    23  		generics := acquireGenerics(len(fields))
    24  		scanErr := rows.Scan(generics...)
    25  		if scanErr != nil {
    26  			releaseGenerics(generics)
    27  			err = scanErr
    28  			return
    29  		}
    30  		entry := Instance[T]()
    31  		writeErr := generics.WriteTo(spec, fields, &entry)
    32  		releaseGenerics(generics)
    33  		if writeErr != nil {
    34  			err = scanErr
    35  			return
    36  		}
    37  		entries = append(entries, entry)
    38  	}
    39  	return
    40  }
    41  
    42  func NewBasicValueWriter(rt reflect.Type) (vw ValueWriter, ct ColumnTypeName, err error) {
    43  	switch rt.Kind() {
    44  	case reflect.String:
    45  		vw = &StringValue{}
    46  		ct = StringType
    47  		break
    48  	case reflect.Bool:
    49  		vw = &BoolValue{}
    50  		ct = BoolType
    51  		break
    52  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    53  		vw = &IntValue{}
    54  		ct = IntType
    55  		break
    56  	case reflect.Float32, reflect.Float64:
    57  		vw = &FloatValue{}
    58  		ct = FloatType
    59  		break
    60  	case reflect.Uint8:
    61  		vw = &ByteValue{}
    62  		ct = ByteType
    63  		break
    64  	default:
    65  		if rt.ConvertibleTo(nullStringType) {
    66  			vw = &StringValue{null: true}
    67  			ct = StringType
    68  			break
    69  		}
    70  		if rt.ConvertibleTo(nullBoolType) {
    71  			vw = &BoolValue{null: true}
    72  			ct = BoolType
    73  			break
    74  		}
    75  		if rt.ConvertibleTo(nullInt64Type) {
    76  			vw = &IntValue{null: true, base: 64}
    77  			ct = IntType
    78  			break
    79  		}
    80  		if rt.ConvertibleTo(nullInt32Type) {
    81  			vw = &IntValue{null: true, base: 32}
    82  			ct = IntType
    83  			break
    84  		}
    85  		if rt.ConvertibleTo(nullInt16Type) {
    86  			vw = &IntValue{null: true, base: 16}
    87  			ct = IntType
    88  			break
    89  		}
    90  		if rt.ConvertibleTo(nullFloatType) {
    91  			vw = &FloatValue{null: true}
    92  			ct = FloatType
    93  			break
    94  		}
    95  		if rt.ConvertibleTo(nullByteType) {
    96  			vw = &ByteValue{null: true}
    97  			ct = ByteType
    98  			break
    99  		}
   100  		if rt.ConvertibleTo(nullBytesType) {
   101  			vw = &BytesValue{null: true}
   102  			ct = BytesType
   103  			break
   104  		}
   105  		if rt.ConvertibleTo(datetimeType) {
   106  			vw = &DatetimeValue{}
   107  			ct = DatetimeType
   108  			break
   109  		}
   110  		if rt.ConvertibleTo(nullTimeType) || rt.ConvertibleTo(nullDatetimeType) {
   111  			vw = &DatetimeValue{null: true}
   112  			ct = DatetimeType
   113  			break
   114  		}
   115  		if rt.ConvertibleTo(dateType) {
   116  			vw = &DateValue{}
   117  			ct = DateType
   118  			break
   119  		}
   120  		if rt.ConvertibleTo(nullTimesDateType) {
   121  			vw = &DateValue{
   122  				null: true,
   123  			}
   124  			ct = DateType
   125  			break
   126  		}
   127  		if rt.ConvertibleTo(timeType) {
   128  			vw = &TimeValue{}
   129  			ct = TimeType
   130  			break
   131  		}
   132  		if rt.ConvertibleTo(nullTimesTimeType) {
   133  			vw = &TimeValue{
   134  				null: true,
   135  			}
   136  			ct = TimeType
   137  			break
   138  		}
   139  		err = errors.Warning("sql: type is not basic").WithCause(fmt.Errorf("%s", rt.String()))
   140  		break
   141  	}
   142  	return
   143  }
   144  
   145  type ValueWriter interface {
   146  	Write(value any, field reflect.Value) (err error)
   147  }
   148  
   149  type StringValue struct {
   150  	null bool
   151  }
   152  
   153  func (w *StringValue) Write(value any, rv reflect.Value) (err error) {
   154  	vv, ok := value.(string)
   155  	if ok {
   156  		if w.null {
   157  			rv.Set(reflect.ValueOf(stdsql.NullString{
   158  				String: vv,
   159  				Valid:  vv != "",
   160  			}).Convert(rv.Type()))
   161  		} else {
   162  			rv.SetString(vv)
   163  		}
   164  		return
   165  	}
   166  	err = errors.Warning("sql: write value failed").
   167  		WithCause(fmt.Errorf("rv is not string"))
   168  	return
   169  }
   170  
   171  type BoolValue struct {
   172  	null bool
   173  }
   174  
   175  func (w *BoolValue) Write(value any, rv reflect.Value) (err error) {
   176  	vv, ok := value.(bool)
   177  	if ok {
   178  		if w.null {
   179  			rv.Set(reflect.ValueOf(stdsql.NullBool{
   180  				Bool:  vv,
   181  				Valid: true,
   182  			}).Convert(rv.Type()))
   183  		} else {
   184  			rv.SetBool(vv)
   185  		}
   186  		return
   187  	}
   188  	err = errors.Warning("sql: write value failed").
   189  		WithCause(fmt.Errorf("rv is not bool"))
   190  	return
   191  }
   192  
   193  type IntValue struct {
   194  	null bool
   195  	base int
   196  }
   197  
   198  func (w *IntValue) Write(value any, rv reflect.Value) (err error) {
   199  	n, ok := AsInt(value)
   200  	if ok {
   201  		if w.null {
   202  			switch w.base {
   203  			case 64:
   204  				rv.Set(reflect.ValueOf(stdsql.NullInt64{
   205  					Int64: n,
   206  					Valid: true,
   207  				}).Convert(rv.Type()))
   208  				break
   209  			case 32:
   210  				rv.Set(reflect.ValueOf(stdsql.NullInt32{
   211  					Int32: int32(n),
   212  					Valid: true,
   213  				}).Convert(rv.Type()))
   214  				break
   215  			default:
   216  				rv.Set(reflect.ValueOf(stdsql.NullInt16{
   217  					Int16: int16(n),
   218  					Valid: true,
   219  				}).Convert(rv.Type()))
   220  				break
   221  			}
   222  		} else {
   223  			rv.SetInt(n)
   224  		}
   225  		return
   226  	}
   227  	err = errors.Warning("sql: write value failed").
   228  		WithCause(fmt.Errorf("rv is not int"))
   229  	return
   230  }
   231  
   232  type FloatValue struct {
   233  	null bool
   234  }
   235  
   236  func (w *FloatValue) Write(value any, rv reflect.Value) (err error) {
   237  	f, ok := AsFloat(value)
   238  	if ok {
   239  		if w.null {
   240  			rv.Set(reflect.ValueOf(stdsql.NullFloat64{
   241  				Float64: f,
   242  				Valid:   true,
   243  			}).Convert(rv.Type()))
   244  		} else {
   245  			rv.SetFloat(f)
   246  		}
   247  		return
   248  	}
   249  	err = errors.Warning("sql: write value failed").
   250  		WithCause(fmt.Errorf("rv is not float"))
   251  	return
   252  }
   253  
   254  type ByteValue struct {
   255  	null bool
   256  }
   257  
   258  func (w *ByteValue) Write(value any, rv reflect.Value) (err error) {
   259  	b, ok := value.(byte)
   260  	if ok {
   261  		if w.null {
   262  			rv.Set(reflect.ValueOf(stdsql.NullByte{
   263  				Byte:  b,
   264  				Valid: true,
   265  			}).Convert(rv.Type()))
   266  		} else {
   267  			rv.Set(reflect.ValueOf(b))
   268  		}
   269  		return
   270  	}
   271  	err = errors.Warning("sql: write value failed").
   272  		WithCause(fmt.Errorf("rv is not byte"))
   273  	return
   274  }
   275  
   276  type BytesValue struct {
   277  	null bool
   278  }
   279  
   280  func (w *BytesValue) Write(value any, rv reflect.Value) (err error) {
   281  	p, ok := value.([]byte)
   282  	if ok {
   283  		if w.null {
   284  			rv.Set(reflect.ValueOf(sql.NullBytes{
   285  				Bytes: p,
   286  				Valid: true,
   287  			}).Convert(rv.Type()))
   288  		} else {
   289  			rv.Set(reflect.ValueOf(p).Convert(rv.Type()))
   290  		}
   291  		return
   292  	}
   293  	err = errors.Warning("sql: write value failed").
   294  		WithCause(fmt.Errorf("rv is not bytes"))
   295  	return
   296  }
   297  
   298  type DatetimeValue struct {
   299  	null bool
   300  }
   301  
   302  func (w *DatetimeValue) Write(value any, rv reflect.Value) (err error) {
   303  	t, ok := value.(time.Time)
   304  	if ok {
   305  		if w.null {
   306  			if rv.Type().ConvertibleTo(nullTimeType) {
   307  				rv.Set(reflect.ValueOf(stdsql.NullTime{
   308  					Time:  t,
   309  					Valid: !t.IsZero(),
   310  				}).Convert(rv.Type()))
   311  			} else if rv.Type().ConvertibleTo(nullDatetimeType) {
   312  				rv.Set(reflect.ValueOf(sql.NullDatetime{
   313  					NullTime: stdsql.NullTime{
   314  						Time:  t,
   315  						Valid: !t.IsZero(),
   316  					},
   317  				}).Convert(rv.Type()))
   318  			}
   319  		} else {
   320  			rv.Set(reflect.ValueOf(t).Convert(rv.Type()))
   321  		}
   322  		return
   323  	}
   324  	err = errors.Warning("sql: write value failed").
   325  		WithCause(fmt.Errorf("rv is not time.Time"))
   326  	return
   327  }
   328  
   329  type DateValue struct {
   330  	null bool
   331  }
   332  
   333  func (w *DateValue) Write(value any, rv reflect.Value) (err error) {
   334  	t, ok := value.(time.Time)
   335  	if ok {
   336  		if w.null {
   337  			rv.Set(reflect.ValueOf(sql.NullDate{
   338  				Date:  times.DataOf(t),
   339  				Valid: !t.IsZero(),
   340  			}).Convert(rv.Type()))
   341  		} else {
   342  			rv.Set(reflect.ValueOf(times.DataOf(t)))
   343  		}
   344  		return
   345  	}
   346  	err = errors.Warning("sql: write value failed").
   347  		WithCause(fmt.Errorf("rv is not time.Time"))
   348  	return
   349  }
   350  
   351  type TimeValue struct {
   352  	null bool
   353  }
   354  
   355  func (w *TimeValue) Write(value any, rv reflect.Value) (err error) {
   356  	t, ok := value.(time.Time)
   357  	if ok {
   358  		if w.null {
   359  			rv.Set(reflect.ValueOf(sql.NullTime{
   360  				Time:  times.TimeOf(t),
   361  				Valid: !t.IsZero(),
   362  			}).Convert(rv.Type()))
   363  		} else {
   364  			rv.Set(reflect.ValueOf(times.TimeOf(t)))
   365  		}
   366  		return
   367  	}
   368  	err = errors.Warning("sql: write value failed").
   369  		WithCause(fmt.Errorf("rv is not time.Time"))
   370  	return
   371  }
   372  
   373  type JsonValue struct {
   374  	ValueType reflect.Type
   375  }
   376  
   377  func (w *JsonValue) Write(value any, rv reflect.Value) (err error) {
   378  	p, ok := value.([]byte)
   379  	if ok {
   380  		if json.IsNull(p) || bytes.Equal(p, jsonEmptyBytes) || bytes.Equal(p, jsonEmptyArrayBytes) {
   381  			return
   382  		}
   383  		if !json.Validate(p) {
   384  			err = errors.Warning("sql: write value failed").
   385  				WithCause(fmt.Errorf("rv is not valid json bytes"))
   386  			return
   387  		}
   388  		if w.ValueType.ConvertibleTo(bytesType) {
   389  			rv.SetBytes(p)
   390  			return
   391  		}
   392  		if w.ValueType.Kind() == reflect.Ptr {
   393  			rv.Set(reflect.New(rv.Type().Elem()))
   394  			decodeErr := json.Unmarshal(p, rv.Interface())
   395  			if decodeErr != nil {
   396  				err = errors.Warning("sql: write value failed").
   397  					WithCause(fmt.Errorf("rv is not valid json bytes")).WithCause(decodeErr)
   398  				return
   399  			}
   400  		} else {
   401  			element := reflect.New(rv.Type()).Interface()
   402  			decodeErr := json.Unmarshal(p, element)
   403  			if decodeErr != nil {
   404  				err = errors.Warning("sql: write value failed").
   405  					WithCause(fmt.Errorf("rv is not valid json bytes")).WithCause(decodeErr)
   406  				return
   407  			}
   408  			rv.Set(reflect.ValueOf(element).Elem())
   409  		}
   410  		return
   411  	}
   412  	err = errors.Warning("sql: write value failed").
   413  		WithCause(fmt.Errorf("rv is not bytes"))
   414  	return
   415  }
   416  
   417  type MappingValue struct {
   418  	ValueType reflect.Type
   419  }
   420  
   421  func (w *MappingValue) Write(value any, rv reflect.Value) (err error) {
   422  	p, ok := value.([]byte)
   423  	if ok {
   424  		if !json.Validate(p) {
   425  			err = errors.Warning("sql: write value failed").
   426  				WithCause(fmt.Errorf("rv is not valid json bytes"))
   427  			return
   428  		}
   429  		if w.ValueType.Kind() == reflect.Ptr {
   430  			rv.Set(reflect.New(rv.Type().Elem()))
   431  			decodeErr := json.Unmarshal(p, rv.Interface())
   432  			if decodeErr != nil {
   433  				err = errors.Warning("sql: write value failed").
   434  					WithCause(fmt.Errorf("rv is not valid json bytes")).WithCause(decodeErr)
   435  				return
   436  			}
   437  		} else {
   438  			element := reflect.New(rv.Type()).Interface()
   439  			decodeErr := json.Unmarshal(p, element)
   440  			if decodeErr != nil {
   441  				err = errors.Warning("sql: write value failed").
   442  					WithCause(fmt.Errorf("rv is not valid json bytes")).WithCause(decodeErr)
   443  				return
   444  			}
   445  			rv.Set(reflect.ValueOf(element).Elem())
   446  		}
   447  		return
   448  	}
   449  	err = errors.Warning("sql: write value failed").
   450  		WithCause(fmt.Errorf("rv is not bytes"))
   451  	return
   452  }
   453  
   454  type ScanValue struct {
   455  }
   456  
   457  func (w *ScanValue) Write(value any, rv reflect.Value) (err error) {
   458  	nv := reflect.New(reflect.Indirect(rv).Type())
   459  	scanner, ok := nv.Interface().(stdsql.Scanner)
   460  	if !ok {
   461  		err = errors.Warning("sql: write value failed").
   462  			WithCause(fmt.Errorf("rv is not sql.Scanner"))
   463  		return
   464  	}
   465  	scanFieldValueErr := scanner.Scan(value)
   466  	if scanFieldValueErr != nil {
   467  		err = errors.Warning("sql: write value failed").
   468  			WithCause(scanFieldValueErr)
   469  		return
   470  	}
   471  	rv.Set(nv.Elem())
   472  	return
   473  }