| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- package column
- import (
- "fmt"
- "reflect"
- "strings"
- "time"
- "github.com/ClickHouse/clickhouse-go/lib/binary"
- )
- type Column interface {
- Name() string
- CHType() string
- ScanType() reflect.Type
- Read(*binary.Decoder, bool) (interface{}, error)
- Write(*binary.Encoder, interface{}) error
- defaultValue() interface{}
- Depth() int
- }
- func Factory(name, chType string, timezone *time.Location) (Column, error) {
- switch chType {
- case "Int8":
- return &Int8{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[int8(0)],
- },
- }, nil
- case "Int16":
- return &Int16{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[int16(0)],
- },
- }, nil
- case "Int32":
- return &Int32{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[int32(0)],
- },
- }, nil
- case "Int64":
- return &Int64{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[int64(0)],
- },
- }, nil
- case "UInt8":
- return &UInt8{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[uint8(0)],
- },
- }, nil
- case "UInt16":
- return &UInt16{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[uint16(0)],
- },
- }, nil
- case "UInt32":
- return &UInt32{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[uint32(0)],
- },
- }, nil
- case "UInt64":
- return &UInt64{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[uint64(0)],
- },
- }, nil
- case "Float32":
- return &Float32{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[float32(0)],
- },
- }, nil
- case "Float64":
- return &Float64{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[float64(0)],
- },
- }, nil
- case "String":
- return &String{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[string("")],
- },
- }, nil
- case "UUID":
- return &UUID{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[string("")],
- },
- }, nil
- case "Date":
- _, offset := time.Unix(0, 0).In(timezone).Zone()
- return &Date{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[time.Time{}],
- },
- Timezone: timezone,
- offset: int64(offset),
- }, nil
- case "IPv4":
- return &IPv4{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[IPv4{}],
- },
- }, nil
- case "IPv6":
- return &IPv6{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[IPv6{}],
- },
- }, nil
- }
- switch {
- case strings.HasPrefix(chType, "DateTime") && !strings.HasPrefix(chType, "DateTime64"):
- return &DateTime{
- base: base{
- name: name,
- chType: "DateTime",
- valueOf: columnBaseTypes[time.Time{}],
- },
- Timezone: timezone,
- }, nil
- case strings.HasPrefix(chType, "DateTime64"):
- return &DateTime64{
- base: base{
- name: name,
- chType: chType,
- valueOf: columnBaseTypes[time.Time{}],
- },
- Timezone: timezone,
- }, nil
- case strings.HasPrefix(chType, "Array"):
- return parseArray(name, chType, timezone)
- case strings.HasPrefix(chType, "Nullable"):
- return parseNullable(name, chType, timezone)
- case strings.HasPrefix(chType, "FixedString"):
- return parseFixedString(name, chType)
- case strings.HasPrefix(chType, "Enum8"), strings.HasPrefix(chType, "Enum16"):
- return parseEnum(name, chType)
- case strings.HasPrefix(chType, "Decimal"):
- return parseDecimal(name, chType)
- case strings.HasPrefix(chType, "SimpleAggregateFunction"):
- if nestedType, err := getNestedType(chType, "SimpleAggregateFunction"); err != nil {
- return nil, err
- } else {
- return Factory(name, nestedType, timezone)
- }
- case strings.HasPrefix(chType, "Tuple"):
- return parseTuple(name, chType, timezone)
- }
- return nil, fmt.Errorf("column: unhandled type %v", chType)
- }
- func getNestedType(chType string, wrapType string) (string, error) {
- prefixLen := len(wrapType) + 1
- suffixLen := 1
- if len(chType) > prefixLen+suffixLen {
- nested := strings.Split(chType[prefixLen:len(chType)-suffixLen], ",")
- if len(nested) == 2 {
- return strings.TrimSpace(nested[1]), nil
- }
- if len(nested) == 3 {
- return strings.TrimSpace(strings.Join(nested[1:], ",")), nil
- }
- }
- return "", fmt.Errorf("column: invalid %s type (%s)", wrapType, chType)
- }
|