diff options
author | vitalyisaev <vitalyisaev@ydb.tech> | 2023-09-22 00:37:24 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@ydb.tech> | 2023-09-22 01:00:33 +0300 |
commit | 375f8187f4f78d9784de1faf6ac79ddef4b365bb (patch) | |
tree | 425314c41432e2b5ffb62496fd1352891eb7454e | |
parent | e74e887de43ac6520b91832a062ff9478c3167c9 (diff) | |
download | ydb-375f8187f4f78d9784de1faf6ac79ddef4b365bb.tar.gz |
YQ Connector: return NULL if date or time value exceeds YQL type value range
-rw-r--r-- | ydb/library/yql/providers/generic/connector/app/server/clickhouse/type_mapper.go | 24 | ||||
-rw-r--r-- | ydb/library/yql/providers/generic/connector/app/server/postgresql/type_mapper.go | 27 |
2 files changed, 39 insertions, 12 deletions
diff --git a/ydb/library/yql/providers/generic/connector/app/server/clickhouse/type_mapper.go b/ydb/library/yql/providers/generic/connector/app/server/clickhouse/type_mapper.go index 42fa693d65..9483fefdd9 100644 --- a/ydb/library/yql/providers/generic/connector/app/server/clickhouse/type_mapper.go +++ b/ydb/library/yql/providers/generic/connector/app/server/clickhouse/type_mapper.go @@ -1,6 +1,7 @@ package clickhouse import ( + "errors" "fmt" "regexp" "time" @@ -19,10 +20,15 @@ type typeMapper struct { } func (tm typeMapper) SQLTypeToYDBColumn(columnName, typeName string) (*Ydb.Column, error) { - var ( - ydbType *Ydb.Type - nullable bool - ) + var ydbType *Ydb.Type + + // By default all columns in CH are non-nullable, so + // we wrap YDB types into Optional type only in such cases: + // + // 1. The column is explicitly defined as nullable; + // 2. The column type is a date/time. CH value ranges for date/time are much wider than YQL value ranges, + // so every time we encounter a value that is out of YQL ranges, we have to return NULL. + nullable := false if matches := tm.isNullable.FindStringSubmatch(typeName); len(matches) > 0 { nullable = true @@ -61,15 +67,19 @@ func (tm typeMapper) SQLTypeToYDBColumn(columnName, typeName string) (*Ydb.Colum case tm.isFixedString.MatchString(typeName): ydbType = &Ydb.Type{Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_STRING}} case typeName == "Date": + nullable = true ydbType = &Ydb.Type{Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATE}} // FIXME: https://st.yandex-team.ru/YQ-2295 // Date32 is not displayed correctly. // case typeName == "Date32": + // nullable = true // ydbType = &Ydb.Type{Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATE}} case typeName == "DateTime": + nullable = true ydbType = &Ydb.Type{Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATETIME}} case tm.isDateTime64.MatchString(typeName): // NOTE: ClickHouse's DateTime64 value range is much more wide than YDB's Timestamp value range + nullable = true ydbType = &Ydb.Type{Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TIMESTAMP}} default: return nil, fmt.Errorf("convert type '%s': %w", typeName, utils.ErrDataTypeNotSupported) @@ -207,6 +217,12 @@ func appendValueToArrowBuilder[IN utils.ValueType, OUT utils.ValueType, AB utils var converter CONV out, err := converter.Convert(value) if err != nil { + if errors.Is(err, utils.ErrValueOutOfTypeBounds) { + // TODO: write warning to logger + builder.AppendNull() + return nil + } + return fmt.Errorf("convert value %v: %w", value, err) } diff --git a/ydb/library/yql/providers/generic/connector/app/server/postgresql/type_mapper.go b/ydb/library/yql/providers/generic/connector/app/server/postgresql/type_mapper.go index c5c5c6fba3..c637ee0f34 100644 --- a/ydb/library/yql/providers/generic/connector/app/server/postgresql/type_mapper.go +++ b/ydb/library/yql/providers/generic/connector/app/server/postgresql/type_mapper.go @@ -1,6 +1,7 @@ package postgresql import ( + "errors" "fmt" "time" @@ -117,16 +118,26 @@ func appendValueToArrowBuilder[IN utils.ValueType, OUT utils.ValueType, AB utils builder array.Builder, valid bool, ) error { - if valid { - var converter CONV - out, err := converter.Convert(value) - if err != nil { - return fmt.Errorf("convert value: %w", err) - } - builder.(AB).Append(out) - } else { + if !valid { builder.AppendNull() + return nil } + + var converter CONV + + out, err := converter.Convert(value) + if err != nil { + if errors.Is(err, utils.ErrValueOutOfTypeBounds) { + // TODO: logger ? + builder.AppendNull() + return nil + } + + return fmt.Errorf("convert value: %w", err) + } + + builder.(AB).Append(out) + return nil } |