Respond to PR feedback.

This commit is contained in:
Nick Tobey
2025-03-20 22:46:46 -07:00
parent 571c89b04d
commit cb2d7a162e
15 changed files with 194 additions and 191 deletions

View File

@@ -23,117 +23,117 @@ import (
type Encoding byte
const (
EncodingNull Encoding = 0
EncodingInt8 Encoding = 1
EncodingUint8 Encoding = 2
EncodingInt16 Encoding = 3
EncodingUint16 Encoding = 4
EncodingInt32 Encoding = 7
EncodingUint32 Encoding = 8
EncodingInt64 Encoding = 9
EncodingUint64 Encoding = 10
EncodingFloat32 Encoding = 11
EncodingFloat64 Encoding = 12
EncodingBit64 Encoding = 13
EncodingHash128 Encoding = 14
EncodingYear Encoding = 15
EncodingDate Encoding = 16
EncodingTime Encoding = 17
EncodingDatetime Encoding = 18
EncodingEnum Encoding = 19
EncodingSet Encoding = 20
EncodingBytesAddr Encoding = 21
EncodingCommitAddr Encoding = 22
EncodingStringAddr Encoding = 23
EncodingJSONAddr Encoding = 24
EncodingCell Encoding = 25
EncodingGeomAddr Encoding = 26
EncodingExtendedAddr Encoding = 27
EncodingString Encoding = 128
EncodingBytes Encoding = 129
EncodingDecimal Encoding = 130
EncodingJSON Encoding = 131
EncodingGeometry Encoding = 133
EncodingExtended Encoding = 134
EncodingStringToast Encoding = 135
EncodingBytesToast Encoding = 136
EncodingExtendedToast Encoding = 137
EncodingNull Encoding = 0
EncodingInt8 Encoding = 1
EncodingUint8 Encoding = 2
EncodingInt16 Encoding = 3
EncodingUint16 Encoding = 4
EncodingInt32 Encoding = 7
EncodingUint32 Encoding = 8
EncodingInt64 Encoding = 9
EncodingUint64 Encoding = 10
EncodingFloat32 Encoding = 11
EncodingFloat64 Encoding = 12
EncodingBit64 Encoding = 13
EncodingHash128 Encoding = 14
EncodingYear Encoding = 15
EncodingDate Encoding = 16
EncodingTime Encoding = 17
EncodingDatetime Encoding = 18
EncodingEnum Encoding = 19
EncodingSet Encoding = 20
EncodingBytesAddr Encoding = 21
EncodingCommitAddr Encoding = 22
EncodingStringAddr Encoding = 23
EncodingJSONAddr Encoding = 24
EncodingCell Encoding = 25
EncodingGeomAddr Encoding = 26
EncodingExtendedAddr Encoding = 27
EncodingString Encoding = 128
EncodingBytes Encoding = 129
EncodingDecimal Encoding = 130
EncodingJSON Encoding = 131
EncodingGeometry Encoding = 133
EncodingExtended Encoding = 134
EncodingStringAdaptive Encoding = 135
EncodingBytesAdaptive Encoding = 136
EncodingExtendedAdaptive Encoding = 137
)
var EnumNamesEncoding = map[Encoding]string{
EncodingNull: "Null",
EncodingInt8: "Int8",
EncodingUint8: "Uint8",
EncodingInt16: "Int16",
EncodingUint16: "Uint16",
EncodingInt32: "Int32",
EncodingUint32: "Uint32",
EncodingInt64: "Int64",
EncodingUint64: "Uint64",
EncodingFloat32: "Float32",
EncodingFloat64: "Float64",
EncodingBit64: "Bit64",
EncodingHash128: "Hash128",
EncodingYear: "Year",
EncodingDate: "Date",
EncodingTime: "Time",
EncodingDatetime: "Datetime",
EncodingEnum: "Enum",
EncodingSet: "Set",
EncodingBytesAddr: "BytesAddr",
EncodingCommitAddr: "CommitAddr",
EncodingStringAddr: "StringAddr",
EncodingJSONAddr: "JSONAddr",
EncodingCell: "Cell",
EncodingGeomAddr: "GeomAddr",
EncodingExtendedAddr: "ExtendedAddr",
EncodingString: "String",
EncodingBytes: "Bytes",
EncodingDecimal: "Decimal",
EncodingJSON: "JSON",
EncodingGeometry: "Geometry",
EncodingExtended: "Extended",
EncodingStringToast: "StringToast",
EncodingBytesToast: "BytesToast",
EncodingExtendedToast: "ExtendedToast",
EncodingNull: "Null",
EncodingInt8: "Int8",
EncodingUint8: "Uint8",
EncodingInt16: "Int16",
EncodingUint16: "Uint16",
EncodingInt32: "Int32",
EncodingUint32: "Uint32",
EncodingInt64: "Int64",
EncodingUint64: "Uint64",
EncodingFloat32: "Float32",
EncodingFloat64: "Float64",
EncodingBit64: "Bit64",
EncodingHash128: "Hash128",
EncodingYear: "Year",
EncodingDate: "Date",
EncodingTime: "Time",
EncodingDatetime: "Datetime",
EncodingEnum: "Enum",
EncodingSet: "Set",
EncodingBytesAddr: "BytesAddr",
EncodingCommitAddr: "CommitAddr",
EncodingStringAddr: "StringAddr",
EncodingJSONAddr: "JSONAddr",
EncodingCell: "Cell",
EncodingGeomAddr: "GeomAddr",
EncodingExtendedAddr: "ExtendedAddr",
EncodingString: "String",
EncodingBytes: "Bytes",
EncodingDecimal: "Decimal",
EncodingJSON: "JSON",
EncodingGeometry: "Geometry",
EncodingExtended: "Extended",
EncodingStringAdaptive: "StringAdaptive",
EncodingBytesAdaptive: "BytesAdaptive",
EncodingExtendedAdaptive: "ExtendedAdaptive",
}
var EnumValuesEncoding = map[string]Encoding{
"Null": EncodingNull,
"Int8": EncodingInt8,
"Uint8": EncodingUint8,
"Int16": EncodingInt16,
"Uint16": EncodingUint16,
"Int32": EncodingInt32,
"Uint32": EncodingUint32,
"Int64": EncodingInt64,
"Uint64": EncodingUint64,
"Float32": EncodingFloat32,
"Float64": EncodingFloat64,
"Bit64": EncodingBit64,
"Hash128": EncodingHash128,
"Year": EncodingYear,
"Date": EncodingDate,
"Time": EncodingTime,
"Datetime": EncodingDatetime,
"Enum": EncodingEnum,
"Set": EncodingSet,
"BytesAddr": EncodingBytesAddr,
"CommitAddr": EncodingCommitAddr,
"StringAddr": EncodingStringAddr,
"JSONAddr": EncodingJSONAddr,
"Cell": EncodingCell,
"GeomAddr": EncodingGeomAddr,
"ExtendedAddr": EncodingExtendedAddr,
"String": EncodingString,
"Bytes": EncodingBytes,
"Decimal": EncodingDecimal,
"JSON": EncodingJSON,
"Geometry": EncodingGeometry,
"Extended": EncodingExtended,
"StringToast": EncodingStringToast,
"BytesToast": EncodingBytesToast,
"ExtendedToast": EncodingExtendedToast,
"Null": EncodingNull,
"Int8": EncodingInt8,
"Uint8": EncodingUint8,
"Int16": EncodingInt16,
"Uint16": EncodingUint16,
"Int32": EncodingInt32,
"Uint32": EncodingUint32,
"Int64": EncodingInt64,
"Uint64": EncodingUint64,
"Float32": EncodingFloat32,
"Float64": EncodingFloat64,
"Bit64": EncodingBit64,
"Hash128": EncodingHash128,
"Year": EncodingYear,
"Date": EncodingDate,
"Time": EncodingTime,
"Datetime": EncodingDatetime,
"Enum": EncodingEnum,
"Set": EncodingSet,
"BytesAddr": EncodingBytesAddr,
"CommitAddr": EncodingCommitAddr,
"StringAddr": EncodingStringAddr,
"JSONAddr": EncodingJSONAddr,
"Cell": EncodingCell,
"GeomAddr": EncodingGeomAddr,
"ExtendedAddr": EncodingExtendedAddr,
"String": EncodingString,
"Bytes": EncodingBytes,
"Decimal": EncodingDecimal,
"JSON": EncodingJSON,
"Geometry": EncodingGeometry,
"Extended": EncodingExtended,
"StringAdaptive": EncodingStringAdaptive,
"BytesAdaptive": EncodingBytesAdaptive,
"ExtendedAdaptive": EncodingExtendedAdaptive,
}
func (v Encoding) String() string {

View File

@@ -510,7 +510,7 @@ func (si *schemaImpl) getKeyColumnsDescriptor(vs val.ValueStore, convertAddressC
switch encoding {
case serial.EncodingExtendedAddr:
handler = val.NewExtendedAddressTypeHandler(vs, extendedType)
case serial.EncodingExtendedToast:
case serial.EncodingExtendedAdaptive:
handler = val.NewToastTypeHandler(vs, extendedType)
default:
// encoding == serial.EncodingExtended
@@ -600,7 +600,7 @@ func (si *schemaImpl) GetValueDescriptor(vs val.ValueStore) val.TupleDesc {
switch encoding {
case serial.EncodingExtendedAddr:
handlers = append(handlers, val.NewExtendedAddressTypeHandler(vs, extendedType))
case serial.EncodingExtendedToast:
case serial.EncodingExtendedAdaptive:
handlers = append(handlers, val.NewToastTypeHandler(vs, extendedType))
default:
// encoding == serial.EncodingExtended

View File

@@ -31,8 +31,8 @@ func EncodingFromSqlType(typ sql.Type) serial.Encoding {
case types.ExtendedTypeSerializedWidth_64K:
return serial.EncodingExtended
case types.ExtendedTypeSerializedWidth_Unbounded:
// Always uses Toast encoding for extended types, regardless of the setting of UseToastTypes below.
return serial.EncodingExtendedToast
// Always uses adaptive encoding for extended types, regardless of the setting of UseAdaptiveEncoding below.
return serial.EncodingExtendedAdaptive
default:
panic(fmt.Errorf("unknown serialization width"))
}
@@ -40,10 +40,10 @@ func EncodingFromSqlType(typ sql.Type) serial.Encoding {
return EncodingFromQueryType(typ.Type())
}
// UseToastTypes indicates whether to use TOAST encoding for large/unbounded fields instead of address encoding.
// Tests can set this variable to true in order to force Dolt to use TOAST encoding for TEXT and BLOB columns.
// Doltgres also sets this to true in order to use TOAST encoding for extended types.
var UseToastTypes = false
// UseAdaptiveEncoding indicates whether to use adaptive encoding for large/unbounded fields instead of address encoding.
// Tests can set this variable to true in order to force Dolt to use adaptive encoding for TEXT and BLOB columns.
// Extended types will always use adaptive encoding for TEXT and BLOB types regardless of this value.
var UseAdaptiveEncoding = false
// EncodingFromQueryType returns a serial.Encoding for a query.Type.
func EncodingFromQueryType(typ query.Type) serial.Encoding {
@@ -103,13 +103,13 @@ func EncodingFromQueryType(typ query.Type) serial.Encoding {
case query.Type_JSON:
return serial.EncodingJSONAddr
case query.Type_BLOB:
if UseToastTypes {
return serial.EncodingBytesToast
if UseAdaptiveEncoding {
return serial.EncodingBytesAdaptive
}
return serial.EncodingBytesAddr
case query.Type_TEXT:
if UseToastTypes {
return serial.EncodingStringToast
if UseAdaptiveEncoding {
return serial.EncodingStringAdaptive
}
return serial.EncodingStringAddr
default:

View File

@@ -106,7 +106,8 @@ func TestSchemaOverrides(t *testing.T) {
// Provide additional test coverage for toast types by running Schema Override tests
// using toast types instead of address types.
func TestSchemaOverridesWithToastTypes(t *testing.T) {
schema.UseToastTypes = true
defer func() { schema.UseAdaptiveEncoding = false }()
schema.UseAdaptiveEncoding = true
harness := newDoltEnginetestHarness(t)
RunSchemaOverridesTest(t, harness)
}

View File

@@ -489,7 +489,7 @@ func getSchemaFragmentsOfType(ctx *sql.Context, tbl *WritableDoltTable, fragType
return nil, err
}
if !ok {
return nil, fmt.Errorf("unexpected type for fragment, expected string, got %v. This should never happen", sqlRow[nameIdx])
return nil, fmt.Errorf("unexpected type for fragment, expected string, got %v. This should never happen", sqlRow[fragmentIdx])
}
frags = append(frags, schemaFragment{

View File

@@ -37,6 +37,7 @@ func unwrapRow(t *testing.T, row sql.Row) (unwrappedRow sql.Row) {
}
return unwrappedRow
}
func unwrapRows(t *testing.T, rows []sql.Row) (unwrappedRows []sql.Row) {
for _, row := range rows {
unwrappedRows = append(unwrappedRows, unwrapRow(t, row))

View File

@@ -50,7 +50,7 @@ enum Encoding : uint8 {
JSON = 131,
Geometry = 133,
Extended = 134,
StringToast = 135,
BytesToast = 136,
ExtendedToast = 137
StringAdaptive = 135,
BytesAdaptive = 136,
ExtendedAdaptive = 137
}

View File

@@ -84,9 +84,9 @@ func countAddresses(items [][]byte, td val.TupleDesc) (cnt int) {
}
return
})
val.IterToastFields(td, func(j int, t val.Type) {
val.IterAdaptiveFields(td, func(j int, t val.Type) {
// get offset of toast value within |tup|
toastValue := val.ToastValue(val.Tuple(items[i]).GetField(j))
toastValue := val.AdaptiveValue(val.Tuple(items[i]).GetField(j))
if toastValue.IsOutlined() {
cnt++
}
@@ -114,12 +114,13 @@ func writeAddressOffsets(b *fb.Builder, items [][]byte, sumSz int, td val.TupleD
b.PrependUint16(uint16(o))
cnt++
})
val.IterToastFields(td, func(j int, t val.Type) {
val.IterAdaptiveFields(td, func(j int, t val.Type) {
// get offset of toast value within |tup|
toastValue := val.ToastValue(val.Tuple(items[i]).GetField(j))
if toastValue.IsOutlined() {
adaptiveValue := val.AdaptiveValue(val.Tuple(items[i]).GetField(j))
if adaptiveValue.IsOutlined() {
// Out-of-line adaptive values end in an address, so get the offset |hash.ByteLen| bytes before the end.
o, _ := tup.GetOffset(j)
o += off + 9 // address appears 9 bytes in.
o += off + len(adaptiveValue) - hash.ByteLen
b.PrependUint16(uint16(o))
cnt++
}

View File

@@ -136,9 +136,9 @@ func GetField(ctx context.Context, td val.TupleDesc, i int, tup val.Tuple, ns No
if ok {
v = val.NewTextStorage(h, ns)
}
case val.BytesToastEnc:
case val.BytesAdaptiveEnc:
v, ok, err = td.GetBytesToastValue(i, ns, tup)
case val.StringToastEnc:
case val.StringAdaptiveEnc:
v, ok, err = td.GetStringToastValue(i, ns, tup)
case val.CommitAddrEnc:
v, ok = td.GetCommitAddr(i, tup)
@@ -300,7 +300,7 @@ func PutField(ctx context.Context, ns NodeStore, tb *val.TupleBuilder, i int, v
return err
}
tb.PutExtendedAddr(i, hash.New(b))
case val.BytesToastEnc:
case val.BytesAdaptiveEnc:
switch value := v.(type) {
case []byte:
err := tb.PutToastBytesFromInline(i, value)
@@ -310,7 +310,7 @@ func PutField(ctx context.Context, ns NodeStore, tb *val.TupleBuilder, i int, v
case *val.ByteArray:
tb.PutToastBytesFromOutline(i, value)
}
case val.StringToastEnc:
case val.StringAdaptiveEnc:
switch value := v.(type) {
case string:
err := tb.PutToastStringFromInline(i, value)
@@ -334,7 +334,7 @@ func getBlobAddrHash(ctx context.Context, ns NodeStore, v interface{}) (h hash.H
}
bytesWrapper, isBytesWrapper := v.(sql.BytesWrapper)
if !isBytesWrapper {
return hash.Hash{}, fmt.Errorf("expected implementation of sql.BytesWrapper, got %v", v)
return hash.Hash{}, fmt.Errorf("expected implementation of sql.BytesWrapper, got %T", v)
}
if byteArray, isByteArray := v.(val.ByteArray); isByteArray {
return byteArray.Addr, nil
@@ -354,7 +354,7 @@ func getStringAddrHash(ctx context.Context, ns NodeStore, v interface{}) (h hash
}
stringWrapper, isStringWrapper := v.(sql.StringWrapper)
if !isStringWrapper {
return hash.Hash{}, fmt.Errorf("expected implementation of sql.StringWrapper, got %v", v)
return hash.Hash{}, fmt.Errorf("expected implementation of sql.StringWrapper, got %T", v)
}
if textStorage, isTextStorage := v.(val.TextStorage); isTextStorage {
return textStorage.Addr, nil

View File

@@ -175,22 +175,22 @@ func TestRoundTripProllyFields(t *testing.T) {
},
{
name: "binary toast short",
typ: val.Type{Enc: val.BytesToastEnc},
typ: val.Type{Enc: val.BytesAdaptiveEnc},
value: []byte("lorem ipsum"),
},
{
name: "binary toast long",
typ: val.Type{Enc: val.BytesToastEnc},
typ: val.Type{Enc: val.BytesAdaptiveEnc},
value: make([]byte, (1 << 12)),
},
{
name: "string toast short",
typ: val.Type{Enc: val.StringToastEnc},
typ: val.Type{Enc: val.StringAdaptiveEnc},
value: "lorem ipsum",
},
{
name: "binary toast long",
typ: val.Type{Enc: val.StringToastEnc},
typ: val.Type{Enc: val.StringAdaptiveEnc},
value: string(make([]byte, (1 << 12))),
},
}

View File

@@ -119,9 +119,9 @@ func IsAddrEncoding(enc Encoding) bool {
func IsToastEncoding(enc Encoding) bool {
switch enc {
case BytesToastEnc,
StringToastEnc,
ExtendedToastEnc:
case BytesAdaptiveEnc,
StringAdaptiveEnc,
ExtendedAdaptiveEnc:
return true
default:
return false
@@ -132,7 +132,7 @@ func IsExtendedEncoding(enc Encoding) bool {
switch enc {
case ExtendedEnc,
ExtendedAddrEnc,
ExtendedToastEnc:
ExtendedAdaptiveEnc:
return true
default:
return false
@@ -141,15 +141,15 @@ func IsExtendedEncoding(enc Encoding) bool {
// Variable Width Encodings
const (
StringEnc = Encoding(serial.EncodingString)
ByteStringEnc = Encoding(serial.EncodingBytes)
DecimalEnc = Encoding(serial.EncodingDecimal)
JSONEnc = Encoding(serial.EncodingJSON)
GeometryEnc = Encoding(serial.EncodingGeometry)
ExtendedEnc = Encoding(serial.EncodingExtended)
StringToastEnc = Encoding(serial.EncodingStringToast)
BytesToastEnc = Encoding(serial.EncodingBytesToast)
ExtendedToastEnc = Encoding(serial.EncodingExtendedToast)
StringEnc = Encoding(serial.EncodingString)
ByteStringEnc = Encoding(serial.EncodingBytes)
DecimalEnc = Encoding(serial.EncodingDecimal)
JSONEnc = Encoding(serial.EncodingJSON)
GeometryEnc = Encoding(serial.EncodingGeometry)
ExtendedEnc = Encoding(serial.EncodingExtended)
StringAdaptiveEnc = Encoding(serial.EncodingStringAdaptive)
BytesAdaptiveEnc = Encoding(serial.EncodingBytesAdaptive)
ExtendedAdaptiveEnc = Encoding(serial.EncodingExtendedAdaptive)
)
func sizeFromType(t Type) (ByteSize, bool) {
@@ -652,7 +652,7 @@ func compareAddr(l, r hash.Hash) int {
return l.Compare(r)
}
func compareToastValue(l, r ToastValue) int {
func compareToastValue(l, r AdaptiveValue) int {
return bytes.Compare(l, r)
}

View File

@@ -110,7 +110,7 @@ func (tb *TupleBuilder) BuildPermissive(pool pool.BuffPool, vs ValueStore) (tup
// do this in a way that doesn't require the full field.
for i, descType := range tb.Desc.Types {
if IsToastEncoding(descType.Enc) {
toastValue := ToastValue(tb.fields[i])
toastValue := AdaptiveValue(tb.fields[i])
outlineSize := toastValue.outlineSize()
inlineSize := toastValue.inlineSize()
@@ -134,7 +134,7 @@ func (tb *TupleBuilder) BuildPermissive(pool pool.BuffPool, vs ValueStore) (tup
// We have enough space, mark all the remaining columns as inline
for j, descType := range tb.Desc.Types[i+1:] {
if IsToastEncoding(descType.Enc) {
toastValue := ToastValue(tb.fields[j+i+1])
toastValue := AdaptiveValue(tb.fields[j+i+1])
if !toastValue.isInlined() {
inline, err := toastValue.convertToInline(ctx, tb.vs, nil)
if err != nil {
@@ -548,13 +548,13 @@ func (tb *TupleBuilder) PutCell(i int, v Cell) {
func (tb *TupleBuilder) PutToastBytesFromInline(i int, v []byte) error {
// TODO: Add context
tb.Desc.expectEncoding(i, BytesToastEnc)
tb.Desc.expectEncoding(i, BytesAdaptiveEnc)
if len(v) > int(MaxTupleDataSize) {
return fmt.Errorf("byte array too large to fit inline (%d > %d). This shouldn't happen", len(v), MaxTupleDataSize)
}
sz := ByteSize(len(v)) + 2 // header byte, plus null terminator?
tb.ensureCapacity(sz)
field := ToastValue(tb.buf[tb.pos : tb.pos+int64(sz)])
field := AdaptiveValue(tb.buf[tb.pos : tb.pos+int64(sz)])
tb.fields[i] = field
field[0] = 0 // Mark this as inline
writeByteString(field[1:], v)
@@ -566,13 +566,13 @@ func (tb *TupleBuilder) PutToastBytesFromInline(i int, v []byte) error {
func (tb *TupleBuilder) PutToastStringFromInline(i int, v string) error {
// TODO: Add context
tb.Desc.expectEncoding(i, StringToastEnc)
tb.Desc.expectEncoding(i, StringAdaptiveEnc)
if len(v) > int(MaxTupleDataSize) {
return fmt.Errorf("byte array too large to fit inline (%d > %d). This shouldn't happen", len(v), MaxTupleDataSize)
}
sz := ByteSize(len(v)) + 2 // header byte, plus null terminator?
tb.ensureCapacity(sz)
field := ToastValue(tb.buf[tb.pos : tb.pos+int64(sz)])
field := AdaptiveValue(tb.buf[tb.pos : tb.pos+int64(sz)])
tb.fields[i] = field
field[0] = 0 // Mark this as inline
writeByteString(field[1:], []byte(v))
@@ -583,7 +583,7 @@ func (tb *TupleBuilder) PutToastStringFromInline(i int, v string) error {
}
func (tb *TupleBuilder) PutToastBytesFromOutline(i int, v *ByteArray) {
tb.Desc.expectEncoding(i, BytesToastEnc)
tb.Desc.expectEncoding(i, BytesAdaptiveEnc)
// TODO: What's the correct size?
sz := ByteSize(29)
tb.ensureCapacity(sz)
@@ -600,7 +600,7 @@ func (tb *TupleBuilder) PutToastBytesFromOutline(i int, v *ByteArray) {
}
func (tb *TupleBuilder) PutToastStringFromOutline(i int, v *TextStorage) {
tb.Desc.expectEncoding(i, StringToastEnc)
tb.Desc.expectEncoding(i, StringAdaptiveEnc)
// TODO: What's the correct size?
sz := ByteSize(29)
tb.ensureCapacity(sz)

View File

@@ -272,7 +272,7 @@ var _ ValueStore = &TestValueStore{}
func TestTupleBuilderToastTypes(t *testing.T) {
ctx := sql.NewEmptyContext()
types := []Type{
{Enc: BytesToastEnc},
{Enc: BytesAdaptiveEnc},
}
vs := &TestValueStore{}
td := NewTupleDescriptor(types...)
@@ -311,8 +311,8 @@ func TestTupleBuilderToastTypes(t *testing.T) {
func TestTupleBuilderMultipleToastTypes(t *testing.T) {
ctx := sql.NewEmptyContext()
types := []Type{
{Enc: BytesToastEnc},
{Enc: BytesToastEnc},
{Enc: BytesAdaptiveEnc},
{Enc: BytesAdaptiveEnc},
}
vs := &TestValueStore{}
td := NewTupleDescriptor(types...)

View File

@@ -150,7 +150,7 @@ func compare(typ Type, left, right []byte) int {
return compareAddr(readAddr(left), readAddr(right))
case CellEnc:
return compareCell(readCell(left), readCell(right))
case BytesToastEnc, StringToastEnc:
case BytesAdaptiveEnc, StringAdaptiveEnc:
return compareToastValue(left, right)
default:
panic("unknown encoding")

View File

@@ -110,10 +110,10 @@ func IterAddressFields(td TupleDesc, cb func(int, Type)) {
}
}
func IterToastFields(td TupleDesc, cb func(int, Type)) {
func IterAdaptiveFields(td TupleDesc, cb func(int, Type)) {
for i, typ := range td.Types {
switch typ.Enc {
case BytesToastEnc, StringToastEnc:
case BytesAdaptiveEnc, StringAdaptiveEnc, ExtendedAdaptiveEnc:
cb(i, typ)
}
}
@@ -526,8 +526,8 @@ func (td TupleDesc) GetBytesAddr(i int, tup Tuple) (hash.Hash, bool) {
// GetBytesToastValue returns either a []byte or a BytesWrapper, but Go doesn't allow us to use a single type for that.
func (td TupleDesc) GetBytesToastValue(i int, vs ValueStore, tup Tuple) (interface{}, bool, error) {
td.expectEncoding(i, BytesToastEnc)
toastValue := ToastValue(td.GetField(i, tup))
td.expectEncoding(i, BytesAdaptiveEnc)
toastValue := AdaptiveValue(td.GetField(i, tup))
if len(toastValue) == 0 {
return nil, false, nil
}
@@ -542,8 +542,8 @@ func (td TupleDesc) GetBytesToastValue(i int, vs ValueStore, tup Tuple) (interfa
}
func (td TupleDesc) GetStringToastValue(i int, vs ValueStore, tup Tuple) (interface{}, bool, error) {
td.expectEncoding(i, StringToastEnc)
toastValue := ToastValue(td.GetField(i, tup))
td.expectEncoding(i, StringAdaptiveEnc)
toastValue := AdaptiveValue(td.GetField(i, tup))
if len(toastValue) == 0 {
return nil, false, nil
}
@@ -784,18 +784,18 @@ func (handler AddressTypeHandler) FormatValue(val any) (string, error) {
return handler.childHandler.FormatValue(val)
}
// A ToastValue is a byte sequence that can represent:
// A AdaptiveValue is a byte sequence that can represent:
// - An inlined string or bytes value
// - An outlined (addressable) string or bytes value
// - NULL (identified by the empty sequence)
// Outlined ToastValues begin with a SQLite () variable-length encoding of the string length.
// Note that this value is always greater than 21, because we only outline values when doing so reduces the length of
// the tuple, and the outlined ToastValue consists of a 20 byte address + the string length (min 1 byte).
// This means that we can use a shorter length value to indicate an inlined ToastValue. We choose 0 for simplicity.
type ToastValue []byte
// the tuple, and the outlined AdaptiveValue consists of a 20 byte address + the string length (min 1 byte).
// This means that we can use a shorter length value to indicate an inlined AdaptiveValue. We choose 0 for simplicity.
type AdaptiveValue []byte
// getMessageLength returns the length of the underlying value.
func (v ToastValue) getMessageLength() int64 {
func (v AdaptiveValue) getMessageLength() int64 {
if v.IsNull() {
return 0
}
@@ -807,7 +807,7 @@ func (v ToastValue) getMessageLength() int64 {
}
// outlineSize computes the size of the value in the tuple if it were outlined.
func (v ToastValue) outlineSize() int64 {
func (v AdaptiveValue) outlineSize() int64 {
if v.IsOutlined() {
return int64(len(v))
}
@@ -816,7 +816,7 @@ func (v ToastValue) outlineSize() int64 {
}
// inlineSize computes the size of the value in the tuple if it were inlined.
func (v ToastValue) inlineSize() int64 {
func (v AdaptiveValue) inlineSize() int64 {
if v.isInlined() {
return int64(len(v))
}
@@ -824,13 +824,13 @@ func (v ToastValue) inlineSize() int64 {
return 1 + blobLength // header + message
}
// IsNull returns whether this ToastValue represents a NULL value.
func (v ToastValue) IsNull() bool {
// IsNull returns whether this AdaptiveValue represents a NULL value.
func (v AdaptiveValue) IsNull() bool {
return len(v) == 0
}
// IsOutlined returns whether this ToastValue represents a outlined addressable value.
func (v ToastValue) IsOutlined() bool {
// IsOutlined returns whether this AdaptiveValue represents a outlined addressable value.
func (v AdaptiveValue) IsOutlined() bool {
if v.IsNull() {
return false
}
@@ -847,7 +847,7 @@ func makeVarInt(x uint64, dest []byte) (bytesWritten int, output []byte) {
// If a conversion is necessary, the converted value will be copied into `dest`. This is a performance
// optimization when there is a pre-allocated buffer.
func (v ToastValue) convertToOutline(ctx context.Context, vs ValueStore, dest []byte) (ToastValue, error) {
func (v AdaptiveValue) convertToOutline(ctx context.Context, vs ValueStore, dest []byte) (AdaptiveValue, error) {
if v.IsOutlined() {
return v, nil
}
@@ -866,8 +866,8 @@ func (v ToastValue) convertToOutline(ctx context.Context, vs ValueStore, dest []
return dest, nil
}
// isInlined returns whether this ToastValue represents an inlined value.
func (v ToastValue) isInlined() bool {
// isInlined returns whether this AdaptiveValue represents an inlined value.
func (v AdaptiveValue) isInlined() bool {
if v.IsNull() {
return false
}
@@ -876,7 +876,7 @@ func (v ToastValue) isInlined() bool {
// If a conversion is necessary, the converted value will be written into `dest`. This is a performance
// optimization when there is a pre-allocated buffer.
func (v ToastValue) convertToInline(ctx context.Context, vs ValueStore, dest []byte) (ToastValue, error) {
func (v AdaptiveValue) convertToInline(ctx context.Context, vs ValueStore, dest []byte) (AdaptiveValue, error) {
if v.isInlined() {
return v, nil
}
@@ -896,7 +896,7 @@ func (v ToastValue) convertToInline(ctx context.Context, vs ValueStore, dest []b
return dest, nil
}
func (v ToastValue) convertToBytes(ctx context.Context, vs ValueStore, buf []byte) ([]byte, error) {
func (v AdaptiveValue) convertToBytes(ctx context.Context, vs ValueStore, buf []byte) ([]byte, error) {
// Only inlined values can be converted to bytes
inlineValue, err := v.convertToInline(ctx, vs, buf)
if err != nil {
@@ -906,7 +906,7 @@ func (v ToastValue) convertToBytes(ctx context.Context, vs ValueStore, buf []byt
return inlineValue[1:], nil
}
func (v ToastValue) convertToByteArray(ctx context.Context, vs ValueStore, buf []byte) (*ByteArray, error) {
func (v AdaptiveValue) convertToByteArray(ctx context.Context, vs ValueStore, buf []byte) (*ByteArray, error) {
// Only outlined values can be converted to a ByteArray
outlineValue, err := v.convertToOutline(ctx, vs, buf)
if err != nil {
@@ -917,7 +917,7 @@ func (v ToastValue) convertToByteArray(ctx context.Context, vs ValueStore, buf [
return NewByteArray(address, vs).WithMaxByteLength(length), nil
}
func (v ToastValue) convertToTextStorage(ctx context.Context, vs ValueStore, buf []byte) (*TextStorage, error) {
func (v AdaptiveValue) convertToTextStorage(ctx context.Context, vs ValueStore, buf []byte) (*TextStorage, error) {
// Only outlined values can be converted to a TextStorage
outlineValue, err := v.convertToOutline(ctx, vs, buf)
if err != nil {
@@ -945,8 +945,8 @@ func NewToastTypeHandler(vs ValueStore, childHandler TupleTypeHandler) ToastType
}
func (handler ToastTypeHandler) SerializedCompare(ctx context.Context, v1 []byte, v2 []byte) (int, error) {
toastValue1 := ToastValue(v1)
toastValue2 := ToastValue(v2)
toastValue1 := AdaptiveValue(v1)
toastValue2 := AdaptiveValue(v2)
// Fast-path: two outlined values with equal hashes are equal.
if toastValue1.IsOutlined() && toastValue2.IsOutlined() && bytes.Equal(toastValue1, toastValue2) {
return 0, nil
@@ -981,7 +981,7 @@ func (handler ToastTypeHandler) SerializeValue(ctx context.Context, val any) ([]
}
func (handler ToastTypeHandler) DeserializeValue(ctx context.Context, val []byte) (any, error) {
toastVal := ToastValue(val)
toastVal := AdaptiveValue(val)
if toastVal.IsNull() {
return nil, nil
}