Skip to content

Commit

Permalink
fix: infer Nullable/Array/LowCardinality with reflection
Browse files Browse the repository at this point in the history
helps re #152

couple fixes needed to get Array(Nullable(...)) & Nullable(DateTime64(...)) cases to work
  • Loading branch information
serprex committed Oct 16, 2024
1 parent a1c9bbc commit 195355a
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 120 deletions.
4 changes: 0 additions & 4 deletions proto/cmd/ch-gen-col/infer.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ package proto
func inferGenerated(t ColumnType) Column {
switch t {
{{- range . }}
case ColumnTypeArray.Sub({{ .ColumnType }}):
return new({{ .Type }}).Array()
case ColumnTypeNullable.Sub({{ .ColumnType }}):
return new({{ .Type }}).Nullable()
case {{ .ColumnType }}:
return new({{ .Type }})
{{- end }}
Expand Down
59 changes: 43 additions & 16 deletions proto/col_auto.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package proto

import (
"reflect"
"strconv"
"strings"

Expand Down Expand Up @@ -37,20 +38,8 @@ func (c *ColAuto) Infer(t ColumnType) error {
switch t {
case ColumnTypeNothing:
c.Data = new(ColNothing)
case ColumnTypeNullable.Sub(ColumnTypeNothing):
c.Data = new(ColNothing).Nullable()
case ColumnTypeArray.Sub(ColumnTypeNothing):
c.Data = new(ColNothing).Array()
case ColumnTypeString:
c.Data = new(ColStr)
case ColumnTypeArray.Sub(ColumnTypeString):
c.Data = new(ColStr).Array()
case ColumnTypeNullable.Sub(ColumnTypeString):
c.Data = new(ColStr).Nullable()
case ColumnTypeLowCardinality.Sub(ColumnTypeString):
c.Data = new(ColStr).LowCardinality()
case ColumnTypeArray.Sub(ColumnTypeLowCardinality.Sub(ColumnTypeString)):
c.Data = new(ColStr).LowCardinality().Array()
case ColumnTypeBool:
c.Data = new(ColBool)
case ColumnTypeDateTime:
Expand All @@ -61,12 +50,50 @@ func (c *ColAuto) Infer(t ColumnType) error {
c.Data = NewMap[string, string](new(ColStr), new(ColStr))
case ColumnTypeUUID:
c.Data = new(ColUUID)
case ColumnTypeArray.Sub(ColumnTypeUUID):
c.Data = new(ColUUID).Array()
case ColumnTypeNullable.Sub(ColumnTypeUUID):
c.Data = new(ColUUID).Nullable()
default:
switch t.Base() {
case ColumnTypeArray:
inner := new(ColAuto)
if err := inner.Infer(t.Elem()); err != nil {
return errors.Wrap(err, "array")
}
innerValue := reflect.ValueOf(inner.Data)
arrayMethod := innerValue.MethodByName("Array")
if arrayMethod.IsValid() && arrayMethod.Type().NumOut() == 1 {
if col, ok := arrayMethod.Call(nil)[0].Interface().(Column); ok {
c.Data = col
c.DataType = t
return nil
}
}
case ColumnTypeNullable:
inner := new(ColAuto)
if err := inner.Infer(t.Elem()); err != nil {
return errors.Wrap(err, "nullable")
}
innerValue := reflect.ValueOf(inner.Data)
nullableMethod := innerValue.MethodByName("Nullable")
if nullableMethod.IsValid() && nullableMethod.Type().NumOut() == 1 {
if col, ok := nullableMethod.Call(nil)[0].Interface().(Column); ok {
c.Data = col
c.DataType = t
return nil
}
}
case ColumnTypeLowCardinality:
inner := new(ColAuto)
if err := inner.Infer(t.Elem()); err != nil {
return errors.Wrap(err, "low cardinality")
}
innerValue := reflect.ValueOf(inner.Data)
lowCardinalityMethod := innerValue.MethodByName("LowCardinality")
if lowCardinalityMethod.IsValid() && lowCardinalityMethod.Type().NumOut() == 1 {
if col, ok := lowCardinalityMethod.Call(nil)[0].Interface().(Column); ok {
c.Data = col
c.DataType = t
return nil
}
}
case ColumnTypeDateTime:
v := new(ColDateTime)
if err := v.Infer(t); err != nil {
Expand Down
100 changes: 0 additions & 100 deletions proto/col_auto_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions proto/col_auto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ func TestColAuto_Infer(t *testing.T) {
"Decimal64(2)",
"Decimal128(3)",
"Decimal256(4)",
"Array(Nullable(Int8))",
"Nullable(DateTime64(3))",
} {
r := AutoResult("foo")
require.NoError(t, r.Data.(Inferable).Infer(columnType))
Expand Down
4 changes: 4 additions & 0 deletions proto/col_datetime64.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ func (c ColDateTime64) Raw() *ColDateTime64Raw {
return &ColDateTime64Raw{ColDateTime64: c}
}

func (c *ColDateTime64) Nullable() *ColNullable[time.Time] {
return &ColNullable[time.Time]{Values: c}
}

func (c *ColDateTime64) Array() *ColArr[time.Time] {
return &ColArr[time.Time]{Data: c}
}
Expand Down
6 changes: 6 additions & 0 deletions proto/col_nullable.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ func (c ColNullable[T]) Row(i int) Nullable[T] {
}
}

func (c *ColNullable[T]) Array() *ColArr[Nullable[T]] {
return &ColArr[Nullable[T]]{
Data: c,
}
}

func (c *ColNullable[T]) Reset() {
c.Nulls.Reset()
c.Values.Reset()
Expand Down

0 comments on commit 195355a

Please sign in to comment.