Skip to content

Commit abd6ab7

Browse files
authored
Merge pull request #435 from ClickHouse/fix-conflicts
fix: column type conflicts
2 parents 0ae6dfb + ab04093 commit abd6ab7

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

proto/column.go

+42-13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package proto
22

33
import (
44
"fmt"
5+
"strconv"
56
"strings"
67

78
"github.com/go-faster/errors"
@@ -83,30 +84,58 @@ func (c ColumnType) Base() ColumnType {
8384
return c[:start]
8485
}
8586

87+
// reduces Decimal(P, ...) to Decimal32/Decimal64/Decimal128/Decimal256
88+
// returns c if any errors occur during conversion
89+
func (c ColumnType) decimalDowncast() ColumnType {
90+
if c.Base() != ColumnTypeDecimal {
91+
return c
92+
}
93+
elem := c.Elem()
94+
precStr, _, _ := strings.Cut(string(elem), ",")
95+
precStr = strings.TrimSpace(precStr)
96+
prec, err := strconv.Atoi(precStr)
97+
if err != nil {
98+
return c
99+
}
100+
switch {
101+
case prec < 10:
102+
return ColumnTypeDecimal32
103+
case prec < 19:
104+
return ColumnTypeDecimal64
105+
case prec < 39:
106+
return ColumnTypeDecimal128
107+
case prec < 77:
108+
return ColumnTypeDecimal256
109+
default:
110+
return c
111+
}
112+
}
113+
86114
// Conflicts reports whether two types conflict.
87115
func (c ColumnType) Conflicts(b ColumnType) bool {
88116
if c == b {
89117
return false
90118
}
91-
{
92-
a := c
93-
if b.Base() == ColumnTypeEnum8 || b.Base() == ColumnTypeEnum16 {
94-
a, b = b, a
95-
}
96-
switch {
97-
case a.Base() == ColumnTypeEnum8 && b == ColumnTypeInt8:
98-
return false
99-
case a.Base() == ColumnTypeEnum16 && b == ColumnTypeInt16:
100-
return false
101-
}
119+
cBase := c.Base()
120+
bBase := b.Base()
121+
if (cBase == ColumnTypeEnum8 && b == ColumnTypeInt8) ||
122+
(cBase == ColumnTypeEnum16 && b == ColumnTypeInt16) ||
123+
(bBase == ColumnTypeEnum8 && c == ColumnTypeInt8) ||
124+
(bBase == ColumnTypeEnum16 && c == ColumnTypeInt16) {
125+
return false
126+
}
127+
if cBase == ColumnTypeDecimal || bBase == ColumnTypeDecimal {
128+
return c.decimalDowncast() != b.decimalDowncast()
102129
}
103-
if c.Base() != b.Base() {
130+
if cBase != bBase {
104131
return true
105132
}
106133
if c.normalizeCommas() == b.normalizeCommas() {
107134
return false
108135
}
109-
switch c.Base() {
136+
switch cBase {
137+
case ColumnTypeArray, ColumnTypeNullable, ColumnTypeLowCardinality:
138+
return c.Elem().Conflicts(b.Elem())
110139
case ColumnTypeDateTime, ColumnTypeDateTime64:
111140
// TODO(ernado): improve check
112141
return false

proto/column_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,15 @@ func TestColumnType_Elem(t *testing.T) {
6060
{A: "Map(String,String)", B: "Map(String, String)"},
6161
{A: "Enum8('increment' = 1, 'gauge' = 2)", B: "Int8"},
6262
{A: "Int8", B: "Enum8('increment' = 1, 'gauge' = 2)"},
63+
{A: "Decimal256", B: "Decimal(76, 38)"},
64+
{A: "Nullable(Decimal256)", B: "Nullable(Decimal(76, 38))"},
6365
} {
6466
assert.False(t, tt.A.Conflicts(tt.B),
6567
"%s ~ %s", tt.A, tt.B,
6668
)
69+
assert.False(t, tt.B.Conflicts(tt.A),
70+
"%s ~ %s", tt.B, tt.A,
71+
)
6772
}
6873
})
6974
t.Run("Incompatible", func(t *testing.T) {
@@ -80,6 +85,9 @@ func TestColumnType_Elem(t *testing.T) {
8085
assert.True(t, tt.A.Conflicts(tt.B),
8186
"%s !~ %s", tt.A, tt.B,
8287
)
88+
assert.True(t, tt.B.Conflicts(tt.A),
89+
"%s !~ %s", tt.B, tt.A,
90+
)
8391
}
8492
})
8593
})

0 commit comments

Comments
 (0)