Skip to content

Commit

Permalink
expression: refactor expression framework
Browse files Browse the repository at this point in the history
  • Loading branch information
sleepymole committed Feb 4, 2023
1 parent 37b3dea commit ad53855
Show file tree
Hide file tree
Showing 54 changed files with 1,698 additions and 2,258 deletions.
59 changes: 21 additions & 38 deletions codec/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ package codec

import (
"encoding/binary"
"fmt"

"github.com/pingcap/errors"
"github.com/vescale/zgraph/datum"
"github.com/vescale/zgraph/parser/model"
"github.com/vescale/zgraph/types"
)
Expand All @@ -37,7 +38,7 @@ func NewPropertyDecoder(labels []*model.LabelInfo, properties []*model.PropertyI
}
}

func (d *PropertyDecoder) Decode(rowData []byte) (map[uint16]struct{}, map[uint16]types.Datum, error) {
func (d *PropertyDecoder) Decode(rowData []byte) (map[uint16]struct{}, map[uint16]datum.Datum, error) {
err := d.fromBytes(rowData)
if err != nil {
return nil, nil, err
Expand All @@ -50,7 +51,7 @@ func (d *PropertyDecoder) Decode(rowData []byte) (map[uint16]struct{}, map[uint1
}
}

row := make(map[uint16]types.Datum)
row := make(map[uint16]datum.Datum)
for _, property := range d.properties {
idx := d.findProperty(property.ID)
if idx >= 0 {
Expand All @@ -66,29 +67,25 @@ func (d *PropertyDecoder) Decode(rowData []byte) (map[uint16]struct{}, map[uint1
return labelIDs, row, nil
}

func (d *PropertyDecoder) decodeColDatum(propData []byte) (types.Datum, error) {
var value types.Datum
kind := types.Kind(propData[0])
switch kind {
case types.KindInt64:
value.SetInt64(decodeInt(propData[1:]))
case types.KindUint64:
value.SetUint64(decodeUint(propData[1:]))
case types.KindString:
value.SetString(string(propData[1:]))
case types.KindBytes:
value.SetBytes(propData[1:])
case types.KindFloat64:
_, fVal, err := DecodeFloat(propData[1:])
func (d *PropertyDecoder) decodeColDatum(propData []byte) (datum.Datum, error) {
var value datum.Datum
typ := types.T(propData[0])
switch typ {
case types.Int:
value = datum.NewInt(decodeInt(propData[1:]))
case types.Float:
_, v, err := DecodeFloat(propData[1:])
if err != nil {
return value, err
return nil, err
}
value.SetFloat64(fVal)
case types.KindDate:
value.SetDate(decodeDate(propData[1:]))
value = datum.NewFloat(v)
case types.String:
value = datum.NewString(string(propData[1:]))
case types.Date:
value = decodeDate(propData[1:])
default:
// TODO: support more types
return value, errors.Errorf("unknown type %d", kind)
return value, fmt.Errorf("unknown type %s", typ)
}
return value, nil
}
Expand All @@ -106,20 +103,6 @@ func decodeInt(val []byte) int64 {
}
}

func decodeUint(val []byte) uint64 {
switch len(val) {
case 1:
return uint64(val[0])
case 2:
return uint64(binary.LittleEndian.Uint16(val))
case 4:
return uint64(binary.LittleEndian.Uint32(val))
default:
return binary.LittleEndian.Uint64(val)
}
}

func decodeDate(val []byte) types.Date {
ct := types.CoreTime(decodeInt(val))
return types.NewDate(ct)
func decodeDate(val []byte) *datum.Date {
return datum.NewDateFromUnixEpochDays(int32(decodeInt(val)))
}
28 changes: 14 additions & 14 deletions codec/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,32 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/vescale/zgraph/datum"
"github.com/vescale/zgraph/parser/model"
"github.com/vescale/zgraph/types"
)

func TestPropertyDecoder_Decode(t *testing.T) {
cases := []struct {
labelIDs []uint16
propertyIDs []uint16
values []types.Datum
values datum.Datums
}{
{
labelIDs: []uint16{1, 2, 3},
propertyIDs: []uint16{1, 2, 3},
values: []types.Datum{
types.NewStringDatum("hello"),
types.NewDatum(1),
types.NewDatum(1.1),
values: datum.Datums{
datum.NewString("hello"),
datum.NewInt(1),
datum.NewFloat(1.1),
},
},
{
labelIDs: []uint16{2, 3, 1},
propertyIDs: []uint16{2, 3, 1},
values: []types.Datum{
types.NewDatum(1),
types.NewDatum(1.1),
types.NewStringDatum("hello"),
values: datum.Datums{
datum.NewInt(1),
datum.NewFloat(1.1),
datum.NewString("hello"),
},
},
}
Expand Down Expand Up @@ -78,10 +78,10 @@ func TestPropertyDecoder_Decode(t *testing.T) {
2: {},
3: {},
}, labelIDs)
assert.Equal(t, map[uint16]types.Datum{
1: types.NewStringDatum("hello"),
2: types.NewDatum(1),
3: types.NewDatum(1.1),
assert.Equal(t, map[uint16]datum.Datum{
1: datum.NewString("hello"),
2: datum.NewInt(1),
3: datum.NewFloat(1.1),
}, row)
}
}
64 changes: 22 additions & 42 deletions codec/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ package codec

import (
"encoding/binary"
"fmt"
"sort"

"github.com/pingcap/errors"
"github.com/vescale/zgraph/types"
"github.com/vescale/zgraph/datum"
)

// PropertyEncoder is used to encode datums into value bytes.
type PropertyEncoder struct {
rowBytes

values []*types.Datum
values datum.Datums
}

// Encode encodes properties into a value bytes.
func (e *PropertyEncoder) Encode(buf []byte, labelIDs, propertyIDs []uint16, values []types.Datum) ([]byte, error) {
func (e *PropertyEncoder) Encode(buf []byte, labelIDs, propertyIDs []uint16, values datum.Datums) ([]byte, error) {
e.reform(labelIDs, propertyIDs, values)
for i, value := range e.values {
err := e.encodeDatum(value)
Expand All @@ -42,23 +42,20 @@ func (e *PropertyEncoder) Encode(buf []byte, labelIDs, propertyIDs []uint16, val
return e.toBytes(buf[:0]), nil
}

func (e *PropertyEncoder) encodeDatum(value *types.Datum) error {
// Put the kind information first.
e.data = append(e.data, byte(value.Kind()))
switch value.Kind() {
case types.KindInt64:
e.data = encodeInt(e.data, value.GetInt64())
case types.KindUint64:
e.data = encodeUint(e.data, value.GetUint64())
case types.KindFloat64:
e.data = EncodeFloat(e.data, value.GetFloat64())
case types.KindString, types.KindBytes:
e.data = append(e.data, value.GetBytes()...)
case types.KindDate:
e.data = encodeDate(e.data, value.GetDate())
func (e *PropertyEncoder) encodeDatum(value datum.Datum) error {
// Put the type information first.
e.data = append(e.data, byte(value.Type()))
switch v := value.(type) {
case *datum.Int:
e.data = encodeInt(e.data, int64(*v))
case *datum.Float:
e.data = EncodeFloat(e.data, float64(*v))
case *datum.String:
e.data = append(e.data, []byte((*v))...)
case *datum.Date:
e.data = encodeDate(e.data, *v)
default:
// TODO: support more types.
return errors.Errorf("unsupported encode type %d", value.Kind())
return fmt.Errorf("unsupported encode type %T", value)
}
return nil
}
Expand All @@ -80,35 +77,18 @@ func encodeInt(buf []byte, iVal int64) []byte {
return buf
}

func encodeUint(buf []byte, uVal uint64) []byte {
var tmp [8]byte
if uint64(uint8(uVal)) == uVal {
buf = append(buf, byte(uVal))
} else if uint64(uint16(uVal)) == uVal {
binary.LittleEndian.PutUint16(tmp[:], uint16(uVal))
buf = append(buf, tmp[:2]...)
} else if uint64(uint32(uVal)) == uVal {
binary.LittleEndian.PutUint32(tmp[:], uint32(uVal))
buf = append(buf, tmp[:4]...)
} else {
binary.LittleEndian.PutUint64(tmp[:], uVal)
buf = append(buf, tmp[:8]...)
}
return buf
}

func encodeDate(buf []byte, date types.Date) []byte {
return encodeInt(buf, int64(date.CoreTime()))
func encodeDate(buf []byte, date datum.Date) []byte {
return encodeInt(buf, int64(date.UnixEpochDays()))
}

func (e *PropertyEncoder) reform(labelIDs, propertyIDs []uint16, values []types.Datum) {
func (e *PropertyEncoder) reform(labelIDs, propertyIDs []uint16, values []datum.Datum) {
e.labelIDs = append(e.labelIDs[:0], labelIDs...)
e.propertyIDs = append(e.propertyIDs[:0], propertyIDs...)
e.offsets = make([]uint16, len(e.propertyIDs))
e.data = e.data[:0]
e.values = e.values[:0]
for i := range values {
e.values = append(e.values, &values[i])
e.values = append(e.values, values[i])
}

sort.Slice(e.labelIDs, func(i, j int) bool {
Expand All @@ -122,7 +102,7 @@ func (e *PropertyEncoder) reform(labelIDs, propertyIDs []uint16, values []types.

type propertySorter struct {
propertyIDs []uint16
values []*types.Datum
values datum.Datums
}

// Less implements the Sorter interface.
Expand Down
12 changes: 6 additions & 6 deletions codec/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/vescale/zgraph/types"
"github.com/vescale/zgraph/datum"
)

func TestPropertyEncoder_Encode(t *testing.T) {
cases := []struct {
labelIDs []uint16
propertyIDs []uint16
values []types.Datum
values datum.Datums
}{
{
labelIDs: []uint16{1, 2, 3},
propertyIDs: []uint16{1, 2, 3},
values: []types.Datum{
types.NewStringDatum("hello"),
types.NewDatum(1),
types.NewDatum(1.1),
values: datum.Datums{
datum.NewString("hello"),
datum.NewInt(1),
datum.NewFloat(1.1),
},
},
}
Expand Down
Loading

0 comments on commit ad53855

Please sign in to comment.