mirror of
https://github.com/dolthub/dolt.git
synced 2026-05-05 11:21:58 -05:00
Move ImmutableTree to val package as ImmutableValue, and move TextStorage and ByteArray into the val package.
This commit is contained in:
@@ -869,7 +869,7 @@ func encodeBytesFromAddress(ctx *sql.Context, addr hash.Hash, ns tree.NodeStore,
|
||||
if ns == nil {
|
||||
return nil, fmt.Errorf("nil NodeStore used to encode bytes from address")
|
||||
}
|
||||
bytes, err := tree.NewByteArray(addr, ns).ToBytes(ctx)
|
||||
bytes, err := ns.ReadBytes(ctx, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
package tree
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/dolthub/dolt/go/store/val"
|
||||
"io"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
@@ -243,42 +243,17 @@ func (b *BlobBuilder) write(ctx context.Context, keys, vals [][]byte, subtrees [
|
||||
return h, nil
|
||||
}
|
||||
|
||||
const bytePeekLength = 128
|
||||
|
||||
type ByteArray struct {
|
||||
ImmutableTree
|
||||
}
|
||||
|
||||
func NewByteArray(addr hash.Hash, ns NodeStore) *ByteArray {
|
||||
return &ByteArray{ImmutableTree{Addr: addr, ns: ns}}
|
||||
}
|
||||
|
||||
func (b *ByteArray) ToBytes(ctx context.Context) ([]byte, error) {
|
||||
return b.bytes(ctx)
|
||||
}
|
||||
|
||||
func (b *ByteArray) ToString(ctx context.Context) (string, error) {
|
||||
buf, err := b.bytes(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
toShow := bytePeekLength
|
||||
if len(buf) < toShow {
|
||||
toShow = len(buf)
|
||||
}
|
||||
return string(buf[:toShow]), nil
|
||||
}
|
||||
|
||||
type JSONDoc struct {
|
||||
ImmutableTree
|
||||
val.ImmutableValue
|
||||
ns NodeStore
|
||||
}
|
||||
|
||||
func NewJSONDoc(addr hash.Hash, ns NodeStore) *JSONDoc {
|
||||
return &JSONDoc{ImmutableTree{Addr: addr, ns: ns}}
|
||||
return &JSONDoc{ImmutableValue: val.NewImmutableValue(addr, ns), ns: ns}
|
||||
}
|
||||
|
||||
func (b *JSONDoc) ToJSONDocument(ctx context.Context) (sqltypes.JSONDocument, error) {
|
||||
buf, err := b.bytes(ctx)
|
||||
buf, err := b.GetBytes(ctx)
|
||||
if err != nil {
|
||||
return sqltypes.JSONDocument{}, err
|
||||
}
|
||||
@@ -291,7 +266,7 @@ func (b *JSONDoc) ToJSONDocument(ctx context.Context) (sqltypes.JSONDocument, er
|
||||
}
|
||||
|
||||
func (b *JSONDoc) ToLazyJSONDocument(ctx context.Context) (sql.JSONWrapper, error) {
|
||||
buf, err := b.bytes(ctx)
|
||||
buf, err := b.GetBytes(ctx)
|
||||
if err != nil {
|
||||
return sqltypes.JSONDocument{}, err
|
||||
}
|
||||
@@ -312,79 +287,13 @@ func (b *JSONDoc) ToIndexedJSONDocument(ctx context.Context) (sql.JSONWrapper, e
|
||||
}
|
||||
|
||||
func (b *JSONDoc) ToString(ctx context.Context) (string, error) {
|
||||
buf, err := b.bytes(ctx)
|
||||
buf, err := b.GetBytes(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
toShow := bytePeekLength
|
||||
toShow := val.BytePeekLength
|
||||
if len(buf) < toShow {
|
||||
toShow = len(buf)
|
||||
}
|
||||
return string(buf[:toShow]), nil
|
||||
}
|
||||
|
||||
type TextStorage struct {
|
||||
ImmutableTree
|
||||
}
|
||||
|
||||
func NewTextStorage(addr hash.Hash, ns NodeStore) *TextStorage {
|
||||
return &TextStorage{ImmutableTree{Addr: addr, ns: ns}}
|
||||
}
|
||||
|
||||
func (b *TextStorage) ToBytes(ctx context.Context) ([]byte, error) {
|
||||
return b.bytes(ctx)
|
||||
}
|
||||
|
||||
func (b *TextStorage) ToString(ctx context.Context) (string, error) {
|
||||
buf, err := b.bytes(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
type ImmutableTree struct {
|
||||
Addr hash.Hash
|
||||
buf []byte
|
||||
ns NodeStore
|
||||
}
|
||||
|
||||
func (t *ImmutableTree) load(ctx context.Context) error {
|
||||
if t.Addr.IsEmpty() {
|
||||
t.buf = []byte{}
|
||||
return nil
|
||||
}
|
||||
n, err := t.ns.Read(ctx, t.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WalkNodes(ctx, n, t.ns, func(ctx context.Context, n Node) error {
|
||||
if n.IsLeaf() {
|
||||
t.buf = append(t.buf, n.GetValue(0)...)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (t *ImmutableTree) bytes(ctx context.Context) ([]byte, error) {
|
||||
if t.buf == nil {
|
||||
err := t.load(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return t.buf[:], nil
|
||||
}
|
||||
|
||||
func (t *ImmutableTree) next() (Node, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (t *ImmutableTree) close() error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (t *ImmutableTree) Read(_ bytes.Buffer) (int, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
@@ -208,8 +208,19 @@ func (ns nodeStore) PurgeCaches() {
|
||||
ns.cache.purge()
|
||||
}
|
||||
|
||||
func (ns nodeStore) ReadBytes(ctx context.Context, h hash.Hash) ([]byte, error) {
|
||||
return NewByteArray(h, ns).ToBytes(ctx)
|
||||
func (ns nodeStore) ReadBytes(ctx context.Context, h hash.Hash) (result []byte, err error) {
|
||||
n, err := ns.Read(ctx, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = WalkNodes(ctx, n, &ns, func(ctx context.Context, n Node) error {
|
||||
if n.IsLeaf() {
|
||||
result = append(result, n.GetValue(0)...)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (ns nodeStore) WriteBytes(ctx context.Context, b []byte) (hash.Hash, error) {
|
||||
@@ -217,4 +228,4 @@ func (ns nodeStore) WriteBytes(ctx context.Context, b []byte) (hash.Hash, error)
|
||||
return h, err
|
||||
}
|
||||
|
||||
var _ val.ValueStore = nodeStore{}
|
||||
var _ val.ValueStore = &nodeStore{}
|
||||
|
||||
@@ -109,7 +109,7 @@ func GetField(ctx context.Context, td val.TupleDesc, i int, tup val.Tuple, ns No
|
||||
var h hash.Hash
|
||||
h, ok = td.GetGeometryAddr(i, tup)
|
||||
if ok {
|
||||
buf, err = NewByteArray(h, ns).ToBytes(ctx)
|
||||
buf, err = ns.ReadBytes(ctx, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -272,8 +272,19 @@ type nodeStoreValidator struct {
|
||||
bbp *sync.Pool
|
||||
}
|
||||
|
||||
func (v nodeStoreValidator) ReadBytes(ctx context.Context, h hash.Hash) ([]byte, error) {
|
||||
panic("not implemented")
|
||||
func (v nodeStoreValidator) ReadBytes(ctx context.Context, h hash.Hash) (result []byte, err error) {
|
||||
n, err := v.ns.Read(ctx, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = WalkNodes(ctx, n, &v, func(ctx context.Context, n Node) error {
|
||||
if n.IsLeaf() {
|
||||
result = append(result, n.GetValue(0)...)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (v nodeStoreValidator) WriteBytes(ctx context.Context, val []byte) (hash.Hash, error) {
|
||||
|
||||
@@ -16,10 +16,12 @@ package val
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/dolthub/dolt/go/store/hash"
|
||||
"github.com/dolthub/go-mysql-server/sql/values"
|
||||
)
|
||||
|
||||
const BytePeekLength = 128
|
||||
|
||||
// ValueStore is an interface for a key-value store that can store byte sequences, keyed by a content hash.
|
||||
// The only implementation is tree.NodeStore, but ValueStore can be used without depending on the tree package.
|
||||
// This is useful for type handlers.
|
||||
@@ -27,3 +29,86 @@ type ValueStore interface {
|
||||
ReadBytes(ctx context.Context, h hash.Hash) ([]byte, error)
|
||||
WriteBytes(ctx context.Context, val []byte) (hash.Hash, error)
|
||||
}
|
||||
|
||||
// ImmutableValue represents a content-addressed value stored in a ValueStore.
|
||||
// The contents are loaded lazily and stored in |Buf|
|
||||
type ImmutableValue struct {
|
||||
Addr hash.Hash
|
||||
Buf []byte
|
||||
vs ValueStore
|
||||
}
|
||||
|
||||
func NewImmutableValue(addr hash.Hash, vs ValueStore) ImmutableValue {
|
||||
return ImmutableValue{Addr: addr, vs: vs}
|
||||
}
|
||||
|
||||
func (t *ImmutableValue) GetBytes(ctx context.Context) ([]byte, error) {
|
||||
if t.Buf == nil {
|
||||
if t.Addr.IsEmpty() {
|
||||
t.Buf = []byte{}
|
||||
return t.Buf, nil
|
||||
}
|
||||
buf, err := t.vs.ReadBytes(ctx, t.Addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.Buf = buf
|
||||
}
|
||||
return t.Buf, nil
|
||||
}
|
||||
|
||||
type TextStorage struct {
|
||||
ImmutableValue
|
||||
}
|
||||
|
||||
func (t TextStorage) Unwrap(ctx context.Context) (string, error) {
|
||||
buf, err := t.GetBytes(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
func (t TextStorage) UnwrapAny(ctx context.Context) (interface{}, error) {
|
||||
return t.Unwrap(ctx)
|
||||
}
|
||||
|
||||
func NewTextStorage(addr hash.Hash, vs ValueStore) *TextStorage {
|
||||
return &TextStorage{NewImmutableValue(addr, vs)}
|
||||
}
|
||||
|
||||
var _ values.Wrapper[string] = &TextStorage{}
|
||||
|
||||
type ByteArray struct {
|
||||
ImmutableValue
|
||||
}
|
||||
|
||||
func NewByteArray(addr hash.Hash, vs ValueStore) *ByteArray {
|
||||
return &ByteArray{NewImmutableValue(addr, vs)}
|
||||
}
|
||||
|
||||
func (b *ByteArray) ToBytes(ctx context.Context) ([]byte, error) {
|
||||
return b.GetBytes(ctx)
|
||||
}
|
||||
|
||||
func (b *ByteArray) ToAny(ctx context.Context) (interface{}, error) {
|
||||
return b.ToBytes(ctx)
|
||||
}
|
||||
|
||||
func (b ByteArray) Unwrap(ctx context.Context) ([]byte, error) {
|
||||
return b.GetBytes(ctx)
|
||||
}
|
||||
|
||||
func (b *ByteArray) ToString(ctx context.Context) (string, error) {
|
||||
buf, err := b.ToBytes(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
toShow := BytePeekLength
|
||||
if len(buf) < toShow {
|
||||
toShow = len(buf)
|
||||
}
|
||||
return string(buf[:toShow]), nil
|
||||
}
|
||||
|
||||
var _ values.Wrapper[[]byte] = &ByteArray{}
|
||||
|
||||
Reference in New Issue
Block a user