Skip to content

Commit b1f8dd2

Browse files
feat: add time and time64 data types support
1 parent 656bc5d commit b1f8dd2

File tree

11 files changed

+901
-7
lines changed

11 files changed

+901
-7
lines changed

proto/_golden/col_time32.hex

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
00000000 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 |................|
2+
00000010 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 |................|
3+
00000020 08 00 00 00 09 00 00 00 0a 00 00 00 0b 00 00 00 |................|
4+
00000030 0c 00 00 00 0d 00 00 00 0e 00 00 00 0f 00 00 00 |................|
5+
00000040 10 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00 |................|
6+
00000050 14 00 00 00 15 00 00 00 16 00 00 00 17 00 00 00 |................|
7+
00000060 18 00 00 00 19 00 00 00 1a 00 00 00 1b 00 00 00 |................|
8+
00000070 1c 00 00 00 1d 00 00 00 1e 00 00 00 1f 00 00 00 |................|
9+
00000080 20 00 00 00 21 00 00 00 22 00 00 00 23 00 00 00 | ...!..."...#...|
10+
00000090 24 00 00 00 25 00 00 00 26 00 00 00 27 00 00 00 |$...%...&...'...|
11+
000000a0 28 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 |(...)...*...+...|
12+
000000b0 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 |,...-......./...|
13+
000000c0 30 00 00 00 31 00 00 00 |0...1...|

proto/_golden/col_time32.raw

200 Bytes
Binary file not shown.

proto/_golden/col_time64.hex

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
00000000 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
2+
00000010 02 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 |................|
3+
00000020 04 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 |................|
4+
00000030 06 00 00 00 00 00 00 00 07 00 00 00 00 00 00 00 |................|
5+
00000040 08 00 00 00 00 00 00 00 09 00 00 00 00 00 00 00 |................|
6+
00000050 0a 00 00 00 00 00 00 00 0b 00 00 00 00 00 00 00 |................|
7+
00000060 0c 00 00 00 00 00 00 00 0d 00 00 00 00 00 00 00 |................|
8+
00000070 0e 00 00 00 00 00 00 00 0f 00 00 00 00 00 00 00 |................|
9+
00000080 10 00 00 00 00 00 00 00 11 00 00 00 00 00 00 00 |................|
10+
00000090 12 00 00 00 00 00 00 00 13 00 00 00 00 00 00 00 |................|
11+
000000a0 14 00 00 00 00 00 00 00 15 00 00 00 00 00 00 00 |................|
12+
000000b0 16 00 00 00 00 00 00 00 17 00 00 00 00 00 00 00 |................|
13+
000000c0 18 00 00 00 00 00 00 00 19 00 00 00 00 00 00 00 |................|
14+
000000d0 1a 00 00 00 00 00 00 00 1b 00 00 00 00 00 00 00 |................|
15+
000000e0 1c 00 00 00 00 00 00 00 1d 00 00 00 00 00 00 00 |................|
16+
000000f0 1e 00 00 00 00 00 00 00 1f 00 00 00 00 00 00 00 |................|
17+
00000100 20 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00 | .......!.......|
18+
00000110 22 00 00 00 00 00 00 00 23 00 00 00 00 00 00 00 |".......#.......|
19+
00000120 24 00 00 00 00 00 00 00 25 00 00 00 00 00 00 00 |$.......%.......|
20+
00000130 26 00 00 00 00 00 00 00 27 00 00 00 00 00 00 00 |&.......'.......|
21+
00000140 28 00 00 00 00 00 00 00 29 00 00 00 00 00 00 00 |(.......).......|
22+
00000150 2a 00 00 00 00 00 00 00 2b 00 00 00 00 00 00 00 |*.......+.......|
23+
00000160 2c 00 00 00 00 00 00 00 2d 00 00 00 00 00 00 00 |,.......-.......|
24+
00000170 2e 00 00 00 00 00 00 00 2f 00 00 00 00 00 00 00 |......../.......|
25+
00000180 30 00 00 00 00 00 00 00 31 00 00 00 00 00 00 00 |0.......1.......|

proto/_golden/col_time64.raw

400 Bytes
Binary file not shown.

proto/cmd/ch-gen-col/main.go

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ const (
2121
KindIP
2222
KindDateTime
2323
KindDate
24+
KindTime32
25+
KindTime64
2426
KindEnum
2527
KindDecimal
2628
KindFixedStr
@@ -168,7 +170,7 @@ func (v Variant) Complex() bool {
168170

169171
func (v Variant) Time() bool {
170172
switch v.Kind {
171-
case KindDate, KindDateTime:
173+
case KindDate, KindDateTime, KindTime32, KindTime64:
172174
return true
173175
default:
174176
return false
@@ -215,6 +217,12 @@ func (v Variant) ElemType() string {
215217
}
216218
return "Date"
217219
}
220+
if v.Kind == KindTime32 {
221+
return "Time32"
222+
}
223+
if v.Kind == KindTime64 {
224+
return "Time64"
225+
}
218226
var b strings.Builder
219227
var (
220228
unsigned = "u"
@@ -312,6 +320,16 @@ func run() error {
312320
Signed: true,
313321
Kind: KindDate,
314322
},
323+
{ // Time32
324+
Bits: 32,
325+
Signed: true,
326+
Kind: KindTime32,
327+
},
328+
{ // Time64
329+
Bits: 64,
330+
Signed: true,
331+
Kind: KindTime64,
332+
},
315333
{ // Enum8
316334
Bits: 8,
317335
Signed: true,
@@ -381,21 +399,25 @@ func run() error {
381399
if v.Kind == KindFixedStr {
382400
base = "col_fixedstr" + strconv.Itoa(v.Bytes())
383401
}
384-
if !v.DateTime() {
402+
if !v.Time() {
385403
if err := write(base+"_gen", v, tpl); err != nil {
386404
return errors.Wrap(err, "write")
387405
}
388406
}
389-
if err := write(base+"_safe_gen", v, tplSafe); err != nil {
390-
return errors.Wrap(err, "write")
407+
if !v.Time() {
408+
if err := write(base+"_safe_gen", v, tplSafe); err != nil {
409+
return errors.Wrap(err, "write")
410+
}
391411
}
392-
if v.GenerateUnsafe {
412+
if v.GenerateUnsafe && !v.Time() {
393413
if err := write(base+"_unsafe_gen", v, tplUnsafe); err != nil {
394414
return errors.Wrap(err, "write")
395415
}
396416
}
397-
if err := write(base+"_gen_test", v, tplTest); err != nil {
398-
return errors.Wrap(err, "write test")
417+
if !v.Time() {
418+
if err := write(base+"_gen_test", v, tplTest); err != nil {
419+
return errors.Wrap(err, "write test")
420+
}
399421
}
400422
}
401423
var infer []Variant

proto/col_auto_gen.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/col_time.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package proto
2+
3+
import (
4+
"encoding/binary"
5+
6+
"github.com/go-faster/errors"
7+
)
8+
9+
var (
10+
_ ColumnOf[Time32] = (*ColTime32)(nil)
11+
_ Inferable = (*ColTime32)(nil)
12+
)
13+
14+
// ColTime32 implements ColumnOf[Time32].
15+
type ColTime32 struct {
16+
Data []Time32
17+
Precision Precision
18+
PrecisionSet bool
19+
}
20+
21+
func (c *ColTime32) WithPrecision(p Precision) *ColTime32 {
22+
c.Precision = p
23+
c.PrecisionSet = true
24+
return c
25+
}
26+
27+
func (c *ColTime32) Reset() {
28+
c.Data = c.Data[:0]
29+
}
30+
31+
func (c ColTime32) Rows() int {
32+
return len(c.Data)
33+
}
34+
35+
func (c ColTime32) Type() ColumnType {
36+
return ColumnTypeTime32
37+
}
38+
39+
func (c *ColTime32) Infer(t ColumnType) error {
40+
return nil
41+
}
42+
43+
func (c ColTime32) Row(i int) Time32 {
44+
return c.Data[i]
45+
}
46+
47+
func (c *ColTime32) Append(v Time32) {
48+
c.Data = append(c.Data, v)
49+
}
50+
51+
func (c *ColTime32) AppendArr(vs []Time32) {
52+
c.Data = append(c.Data, vs...)
53+
}
54+
55+
func (c *ColTime32) LowCardinality() *ColLowCardinality[Time32] {
56+
return &ColLowCardinality[Time32]{
57+
index: c,
58+
}
59+
}
60+
61+
func (c *ColTime32) Array() *ColArr[Time32] {
62+
return &ColArr[Time32]{
63+
Data: c,
64+
}
65+
}
66+
67+
func (c *ColTime32) Nullable() *ColNullable[Time32] {
68+
return &ColNullable[Time32]{
69+
Values: c,
70+
}
71+
}
72+
73+
func NewArrTime32() *ColArr[Time32] {
74+
return &ColArr[Time32]{
75+
Data: &ColTime32{},
76+
}
77+
}
78+
79+
// ColTime is an alias for ColTime32
80+
type ColTime = ColTime32
81+
82+
func (c *ColTime32) DecodeColumn(r *Reader, rows int) error {
83+
if rows == 0 {
84+
return nil
85+
}
86+
const size = 32 / 8
87+
data, err := r.ReadRaw(rows * size)
88+
if err != nil {
89+
return errors.Wrap(err, "read")
90+
}
91+
v := c.Data
92+
// Move bound check out of loop.
93+
//
94+
// See https://github.com/golang/go/issues/30945.
95+
_ = data[len(data)-size]
96+
for i := 0; i <= len(data)-size; i += size {
97+
v = append(v,
98+
Time32(binary.LittleEndian.Uint32(data[i:i+size])),
99+
)
100+
}
101+
c.Data = v
102+
return nil
103+
}
104+
105+
// EncodeColumn encodes Time32 rows to *Buffer.
106+
func (c ColTime32) EncodeColumn(b *Buffer) {
107+
v := c.Data
108+
if len(v) == 0 {
109+
return
110+
}
111+
const size = 32 / 8
112+
offset := len(b.Buf)
113+
b.Buf = append(b.Buf, make([]byte, size*len(v))...)
114+
for _, vv := range v {
115+
binary.LittleEndian.PutUint32(
116+
b.Buf[offset:offset+size],
117+
uint32(vv),
118+
)
119+
offset += size
120+
}
121+
}
122+
123+
func (c ColTime32) WriteColumn(w *Writer) {
124+
w.ChainBuffer(c.EncodeColumn)
125+
}

proto/col_time64.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package proto
2+
3+
import (
4+
"encoding/binary"
5+
"fmt"
6+
"strconv"
7+
8+
"github.com/go-faster/errors"
9+
)
10+
11+
var (
12+
_ ColumnOf[Time64] = (*ColTime64)(nil)
13+
_ Inferable = (*ColTime64)(nil)
14+
)
15+
16+
// ColTime64 implements ColumnOf[Time64].
17+
type ColTime64 struct {
18+
Data []Time64
19+
Precision Precision
20+
PrecisionSet bool
21+
}
22+
23+
func (c *ColTime64) Reset() {
24+
c.Data = c.Data[:0]
25+
}
26+
27+
func (c ColTime64) Rows() int {
28+
return len(c.Data)
29+
}
30+
31+
func (c ColTime64) Type() ColumnType {
32+
return ColumnTypeTime64.With(fmt.Sprintf("%d", c.Precision))
33+
}
34+
35+
func (c *ColTime64) Infer(t ColumnType) error {
36+
elem := t.Elem()
37+
if elem == "" {
38+
c.Precision = PrecisionNano
39+
return nil
40+
}
41+
42+
precision, err := strconv.Atoi(string(elem))
43+
if err != nil {
44+
return errors.Wrap(err, "parse precision")
45+
}
46+
47+
if precision < 0 || precision > 9 {
48+
return errors.New("precision must be between 0 and 9")
49+
}
50+
51+
c.Precision = Precision(precision)
52+
return nil
53+
}
54+
55+
func (c ColTime64) Row(i int) Time64 {
56+
return c.Data[i]
57+
}
58+
59+
func (c *ColTime64) Append(v Time64) {
60+
c.Data = append(c.Data, v)
61+
}
62+
63+
func (c *ColTime64) AppendArr(vs []Time64) {
64+
c.Data = append(c.Data, vs...)
65+
}
66+
67+
func (c *ColTime64) LowCardinality() *ColLowCardinality[Time64] {
68+
return &ColLowCardinality[Time64]{
69+
index: c,
70+
}
71+
}
72+
73+
func (c *ColTime64) Array() *ColArr[Time64] {
74+
return &ColArr[Time64]{
75+
Data: c,
76+
}
77+
}
78+
79+
func (c *ColTime64) Nullable() *ColNullable[Time64] {
80+
return &ColNullable[Time64]{
81+
Values: c,
82+
}
83+
}
84+
85+
func NewArrTime64() *ColArr[Time64] {
86+
return &ColArr[Time64]{
87+
Data: &ColTime64{},
88+
}
89+
}
90+
91+
func (c *ColTime64) WithPrecision(p Precision) *ColTime64 {
92+
c.Precision = p
93+
c.PrecisionSet = true
94+
return c
95+
}
96+
97+
func (c *ColTime64) DecodeColumn(r *Reader, rows int) error {
98+
if rows == 0 {
99+
return nil
100+
}
101+
const size = 64 / 8
102+
data, err := r.ReadRaw(rows * size)
103+
if err != nil {
104+
return errors.Wrap(err, "read")
105+
}
106+
v := c.Data
107+
// Move bound check out of loop.
108+
//
109+
// See https://github.com/golang/go/issues/30945.
110+
_ = data[len(data)-size]
111+
for i := 0; i <= len(data)-size; i += size {
112+
v = append(v,
113+
Time64(binary.LittleEndian.Uint64(data[i:i+size])),
114+
)
115+
}
116+
c.Data = v
117+
return nil
118+
}
119+
120+
// EncodeColumn encodes Time64 rows to *Buffer.
121+
func (c ColTime64) EncodeColumn(b *Buffer) {
122+
v := c.Data
123+
if len(v) == 0 {
124+
return
125+
}
126+
const size = 64 / 8
127+
offset := len(b.Buf)
128+
b.Buf = append(b.Buf, make([]byte, size*len(v))...)
129+
for _, vv := range v {
130+
binary.LittleEndian.PutUint64(
131+
b.Buf[offset:offset+size],
132+
uint64(vv),
133+
)
134+
offset += size
135+
}
136+
}
137+
138+
func (c ColTime64) WriteColumn(w *Writer) {
139+
w.ChainBuffer(c.EncodeColumn)
140+
}

0 commit comments

Comments
 (0)