tuple.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package column
  2. import (
  3. "fmt"
  4. "github.com/ClickHouse/clickhouse-go/lib/binary"
  5. "reflect"
  6. "strconv"
  7. "time"
  8. )
  9. type Tuple struct {
  10. base
  11. columns []Column
  12. }
  13. func (tuple *Tuple) Read(decoder *binary.Decoder, isNull bool) (interface{}, error) {
  14. return nil, fmt.Errorf("do not use Read method for Tuple(T) column")
  15. }
  16. func (tuple *Tuple) ReadTuple(decoder *binary.Decoder, rows int) ([]interface{}, error) {
  17. var values = make([][]interface{}, rows)
  18. for _, c := range tuple.columns {
  19. switch column := c.(type) {
  20. case *Array:
  21. cols, err := column.ReadArray(decoder, rows)
  22. if err != nil {
  23. return nil, err
  24. }
  25. for i := 0; i < rows; i++ {
  26. values[i] = append(values[i], cols[i])
  27. }
  28. case *Nullable:
  29. cols, err := column.ReadNull(decoder, rows)
  30. if err != nil {
  31. return nil, err
  32. }
  33. for i := 0; i < rows; i++ {
  34. values[i] = append(values[i], cols[i])
  35. }
  36. case *Tuple:
  37. cols, err := column.ReadTuple(decoder, rows)
  38. if err != nil {
  39. return nil, err
  40. }
  41. for i := 0; i < rows; i++ {
  42. values[i] = append(values[i], cols[i])
  43. }
  44. default:
  45. for i := 0; i < rows; i++ {
  46. value, err := c.Read(decoder, false)
  47. if err != nil {
  48. return nil, err
  49. }
  50. values[i] = append(values[i], value)
  51. }
  52. }
  53. }
  54. var ret = make([]interface{}, rows)
  55. for i := range values {
  56. ret[i] = values[i]
  57. }
  58. return ret, nil
  59. }
  60. func (tuple *Tuple) Write(encoder *binary.Encoder, v interface{}) (err error) {
  61. return fmt.Errorf("unsupported Tuple(T) type [%T]", v)
  62. }
  63. func parseTuple(name, chType string, timezone *time.Location) (Column, error) {
  64. var columnType = chType
  65. chType = chType[6 : len(chType)-1]
  66. var types []string
  67. var last, diff int
  68. for i, b := range chType + "," {
  69. if b == '(' {
  70. diff++
  71. } else if b == ')' {
  72. diff--
  73. } else if b == ',' && diff == 0 {
  74. types = append(types, chType[last:i])
  75. last = i + 2
  76. }
  77. }
  78. var columns = make([]Column, 0, len(types))
  79. for i, chType := range types {
  80. column, err := Factory(name+"."+strconv.Itoa(i+1), chType, timezone)
  81. if err != nil {
  82. return nil, fmt.Errorf("%s: %v", chType, err)
  83. }
  84. columns = append(columns, column)
  85. }
  86. return &Tuple{
  87. base: base{
  88. name: name,
  89. chType: columnType,
  90. valueOf: reflect.ValueOf([]interface{}{}),
  91. },
  92. columns: columns,
  93. }, nil
  94. }