nullable.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package column
  2. import (
  3. "fmt"
  4. "reflect"
  5. "time"
  6. "github.com/ClickHouse/clickhouse-go/lib/binary"
  7. )
  8. type Nullable struct {
  9. base
  10. column Column
  11. }
  12. func (null *Nullable) ScanType() reflect.Type {
  13. return reflect.PtrTo(null.column.ScanType())
  14. }
  15. func (null *Nullable) Read(decoder *binary.Decoder, isNull bool) (interface{}, error) {
  16. return null.column.Read(decoder, isNull)
  17. }
  18. func (null *Nullable) Write(encoder *binary.Encoder, v interface{}) error {
  19. return nil
  20. }
  21. func (null *Nullable) ReadNull(decoder *binary.Decoder, rows int) (_ []interface{}, err error) {
  22. var (
  23. isNull byte
  24. value interface{}
  25. nulls = make([]byte, rows)
  26. values = make([]interface{}, rows)
  27. )
  28. for i := 0; i < rows; i++ {
  29. if isNull, err = decoder.ReadByte(); err != nil {
  30. return nil, err
  31. }
  32. nulls[i] = isNull
  33. }
  34. for i, isNull := range nulls {
  35. switch value, err = null.column.Read(decoder, isNull != 0); true {
  36. case err != nil:
  37. return nil, err
  38. case isNull == 0:
  39. values[i] = value
  40. default:
  41. values[i] = nil
  42. }
  43. }
  44. return values, nil
  45. }
  46. func (null *Nullable) WriteNull(nulls, encoder *binary.Encoder, v interface{}) error {
  47. if isNil(v) {
  48. if _, err := nulls.Write([]byte{1}); err != nil {
  49. return err
  50. }
  51. return null.column.Write(encoder, null.column.defaultValue())
  52. }
  53. if _, err := nulls.Write([]byte{0}); err != nil {
  54. return err
  55. }
  56. return null.column.Write(encoder, v)
  57. }
  58. func parseNullable(name, chType string, timezone *time.Location) (*Nullable, error) {
  59. if len(chType) < 14 {
  60. return nil, fmt.Errorf("invalid Nullable column type: %s", chType)
  61. }
  62. column, err := Factory(name, chType[9:][:len(chType)-10], timezone)
  63. if err != nil {
  64. return nil, fmt.Errorf("Nullable(T): %v", err)
  65. }
  66. return &Nullable{
  67. base: base{
  68. name: name,
  69. chType: chType,
  70. },
  71. column: column,
  72. }, nil
  73. }
  74. func (null *Nullable) GetColumn() Column {
  75. return null.column
  76. }
  77. func isNil(v interface{}) bool {
  78. if v == nil {
  79. return true
  80. }
  81. switch val := reflect.ValueOf(v); val.Type().Kind() {
  82. case reflect.Array, reflect.Chan, reflect.Map, reflect.Ptr, reflect.Slice:
  83. return val.IsNil()
  84. }
  85. return false
  86. }