chunk

package
v0.40.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 22, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package chunk implements the zero-alloc value-column codecs (DESIGN.md §14 M0): delta-of-delta timestamps, Gorilla XOR float gauges, T64, dictionary, and scaled-decimal+nearest-delta. Each codec is an append-style Encode(dst []byte, ...) []byte over bitstream and is fuzzed for round-trip identity. Not yet implemented (M0 in progress; bitstream is the first foundation).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecodeBytes

func DecodeBytes(dst [][]byte, src []byte) ([][]byte, int, error)

DecodeBytes decodes a dictionary-encoded column from src into dst. Returned byte slices alias src.

func DecodeBytesRawBlob added in v0.32.0

func DecodeBytesRawBlob(src []byte) (blob []byte, width, rows int, err error)

DecodeBytesRawBlob decodes a flagFixed-encoded column (as written by EncodeBytesRaw/ EncodeBytesRawBlob) into its flat form: the contiguous rows×width backing blob, width, and row count — with no per-row [][]byte slice headers built over it, unlike DecodeBytes/ DecodeBytesDict. This is the shape a stride/SIMD equality scan operates on directly. The returned blob aliases src. It returns [errNotFixedWidth] if the stream is not flagFixed (e.g. a dictionary or flat-fallback stream from a low- or mixed-width column).

func DecodeFloats

func DecodeFloats(dst []float64, src []byte) ([]float64, int, error)

DecodeFloats decodes a Gorilla XOR encoded float64 column from src into dst.

func DecodeFloatsDecimal

func DecodeFloatsDecimal(dst []float64, src []byte) ([]float64, int, error)

DecodeFloatsDecimal decodes a scaled-decimal + nearest-delta encoded float64 column.

func DecodeIntsT64

func DecodeIntsT64(dst []int64, src []byte) ([]int64, int, error)

DecodeIntsT64 decodes a T64-encoded int64 column from src into dst.

func DecodeTimestamps

func DecodeTimestamps(dst []int64, src []byte) ([]int64, int, error)

DecodeTimestamps decodes a DoD-encoded timestamp column from src into dst (growing it as needed) and returns the result with the number of source bytes consumed.

func EncodeBytes

func EncodeBytes(dst []byte, vals [][]byte) []byte

EncodeBytes appends a dictionary-encoded []byte column to dst and returns the extended slice (DESIGN.md §6, §14 M0).

It uses a pool.ByteIntMap (xxh3-based open-addressing hash table) instead of Go's map[string]int: xxh3 is faster than the runtime's string hash, and []byte keys avoid the string-conversion allocation on every lookup. For low-cardinality columns (≤256 distinct), each row id is 1 byte.

Layout: [uvarint rows] [1 byte flag] [payload]

flagDict payload: [uvarint dictSize] [dict entries: per entry uvarint len + bytes] [row ids: 1 byte each if dictSize ≤ 256, else 2 bytes big-endian each]

flagFlat payload: per row [uvarint len]bytes (the flat fallback for >65536 distinct).

For repeated encodes of many column batches, prefer a DictEncoder: it keeps the hash table and scratch slices cache-warm across calls instead of paying the sync.Pool Get/Put on each call.

func EncodeBytesBlob added in v0.25.0

func EncodeBytesBlob(dst, blob []byte, offsets []int32) []byte

EncodeBytesBlob is EncodeBytes over the blob+offsets column form (cell i is blob[offsets[i]:offsets[i+1]]; len(offsets) == rows+1, offsets[0] == 0). The output is byte-identical to EncodeBytes over the equivalent [][]byte, without materializing a view per row.

func EncodeBytesBlobRange added in v0.37.0

func EncodeBytesBlobRange(dst, blob []byte, offsets []int32, lo, hi int) []byte

EncodeBytesBlobRange is EncodeBytesBlob over rows [lo,hi) of a blob column, for block-framed encoding where each granule is an independent stream. Offsets are absolute into blob, so the sub-range needs no rebasing — cell i of the range is blob[offsets[lo+i]:offsets[lo+i+1]] either way — which is what keeps per-granule encoding allocation-free.

Each granule builds its own dictionary, so a granule of low-cardinality values dictionary-encodes while one of near-unique values degrades to the flat form independently. That is what makes the choice per granule rather than per column: a part whose column is mostly structured but holds one stretch of unique values (a stack trace among clean log lines) keeps the dictionary everywhere else, where a per-column decision would drop it for the whole part.

func EncodeBytesDict added in v0.38.0

func EncodeBytesDict(dst []byte, entries [][]byte, ids []int32) []byte

EncodeBytesDict appends a dictionary-encoded []byte column to dst for a column already held in split form — a deduplicated entry table plus one entry index per row — and returns the extended slice. It is EncodeBytes without the per-row hashing: the entry indices are remapped to output dictionary ids through an array, so no value is hashed or compared.

The output is byte-identical to EncodeBytes over the materialized rows (entries[ids[i]] for each i), including the flat fallback above 65536 distinct values, provided the caller honors the preconditions:

  • entries must be distinct by value. EncodeBytes deduplicates by value; this deduplicates by index, so two indices holding equal bytes produce two dictionary entries — a valid stream, but not the same one.
  • every ids[i] must be in [0, len(entries)). This one *is* checked, and panics naming the row, the id and the table size — the two halves come from different places in the caller, so the bare bounds error it replaces was the hard kind to debug. Distinctness is not checked: it costs a hash per entry, which is most of what this function exists to avoid.

func EncodeBytesDictRange added in v0.38.0

func EncodeBytesDictRange(dst []byte, entries [][]byte, ids []int32, lo, hi int) []byte

EncodeBytesDictRange is EncodeBytesDict over rows [lo,hi) of ids, for block-framed encoding where each granule is an independent stream with its own dictionary (see EncodeBytesBlobRange). It panics unless 0 <= lo <= hi <= len(ids).

func EncodeBytesRaw added in v0.2.0

func EncodeBytesRaw(dst []byte, vals [][]byte) []byte

EncodeBytesRaw encodes a byte-string column without a dictionary (CodecBytesRaw): when every value shares one length it writes a single shared width followed by the values back-to-back (the fixed-width form, ideal for id columns); otherwise it falls back to the same length-prefixed inline layout as the dictionary codec's flat fallback. The output is a self-describing bytes-column stream that DecodeBytes and DecodeBytesDict read directly.

Layout: [uvarint rows] [1 byte flag] [payload]

flagFixed payload: [uvarint width] [rows × width bytes]
flagFlat  payload: per row [uvarint len][bytes]

func EncodeBytesRawBlob added in v0.25.0

func EncodeBytesRawBlob(dst, blob []byte, offsets []int32) []byte

EncodeBytesRawBlob is EncodeBytesRaw over the blob+offsets column form (see EncodeBytesBlob); the output is byte-identical to EncodeBytesRaw over the equivalent [][]byte.

func EncodeBytesRawBlobRange added in v0.37.0

func EncodeBytesRawBlobRange(dst, blob []byte, offsets []int32, lo, hi int) []byte

EncodeBytesRawBlobRange is EncodeBytesRawBlob over rows [lo,hi) of a blob column.

func EncodeFloats

func EncodeFloats(dst []byte, vals []float64) []byte

EncodeFloats appends a Gorilla XOR encoded float64 column to dst and returns the extended slice (DESIGN.md §6, §14 M0; Prometheus/Gorilla-style).

Layout: [uvarint rows] [bitstream payload]:

row 0:  raw64(Float64bits(v0))    // 64 raw bits, MSB-first
row 1+: xor-delta(v_n, v_{n-1})  // per the 3-case prefix below

The XOR control-bit cases (delta = Float64bits(new) XOR Float64bits(prev)):

0b0                    → delta == 0, value unchanged         (1 bit)
0b10 + M bits          → reuse prev leading/trailing, M = 64-leading-trailing
0b11 + 5b lead + 6b sig + S bits → new leading/trailing, S = sig (0→64 sentinel)

Leading-zero count is clamped to 31 (5-bit field). The significant-bit count is stored in 6 bits; 0 is a sentinel meaning 64 (when leading==trailing==0). The meaningful XOR bits are stored right-shifted by trailing (the trailing zeros are dropped and re-shifted on decode).

func EncodeFloatsDecimal

func EncodeFloatsDecimal(dst []byte, vals []float64, precisionBits uint8) []byte

EncodeFloatsDecimal appends a scaled-decimal + nearest-delta encoded float64 column to dst (DESIGN.md §6, §14 M0; VictoriaMetrics-style). precisionBits controls the lossiness: 64 = lossless (no bit zeroing), <64 = lossy (zeros trailing low bits of deltas so the varint stream is ZSTD-compressible, reaching ~0.4–0.8 B/point).

Layout: [uvarint rows] [varint exponent] [uvarint precisionBits]

[zigzag-varint v0] [zigzag-varint delta1] ... [zigzag-varint deltaN-1]

Pipeline:

  1. Convert each float64 to a scaled int64 with a shared exponent e: f ≈ v * 10^e. The mantissa is minimized (trailing decimal zeros stripped into e).
  2. Compute first differences: d_n = v_n - v_{n-1}.
  3. If precisionBits < 64, zero the trailing (originBits - precisionBits) low bits of each delta (the "nearest-delta" step), with counter-reset hysteresis.
  4. Zigzag-varint encode the deltas; v0 is stored out-of-band.

With precisionBits=64 the round-trip is exact for integer-valued floats and near-exact (within float64 rounding) for fractional values. With precisionBits<64 the codec is deliberately lossy.

func EncodeIntsT64

func EncodeIntsT64(dst []byte, vals []int64) []byte

EncodeIntsT64 appends a T64-encoded int64 column to dst (DESIGN.md §6, §14 M0; ClickHouse T64: bit-transpose + crop of unused high bits).

Layout: [uvarint rows] [8 bytes min] [8 bytes max] [transposed valuable bits]

The valuable-bit count is numBits = 64 - clz(min ^ max). If min == max (numBits==0), only the header is stored (constant column). Otherwise the values are processed in blocks of 64: each block is transposed so that bit j of all 64 values sits in a single uint64, and only the lowest numBits transposed rows are emitted (the high zero bits are cropped). On decode the cropped high bits are restored by OR-ing the common high prefix (min & ~((1<<numBits)-1)).

This codec is lossless. It is a preprocessor: the output is designed to be fed to a general compressor (ZSTD/LZ4) which benefits from the transposed, repetitive layout.

func EncodeTimestamps

func EncodeTimestamps(dst []byte, ts []int64) []byte

EncodeTimestamps appends a delta-of-delta encoded timestamp column to dst and returns the extended slice (DESIGN.md §6, §14 M0; Prometheus-style).

Layout: [uvarint rows] [bitstream payload]:

row 0:  varint(t0)                 // signed zigzag varint, absolute timestamp
row 1:  uvarint(t1 - t0)           // unsigned varint, first delta
row 2+: dod(t_n)                   // delta-of-delta, 5-case prefix (see below)

The DoD bit layout (dod = tDelta_n - tDelta_{n-1}):

0b0              + 0  bits  → dod == 0            (1 bit total)
0b10             + 14 bits  → |dod| ≤ 2^13        (16 bits)
0b110            + 17 bits  → |dod| ≤ 2^16        (20 bits)
0b1110           + 20 bits  → |dod| ≤ 2^19        (24 bits)
0b1111           + 64 bits  → escape, full int64  (68 bits)

The 14/17/20-bit values are stored as unsigned two's-complement and sign-extended on decode (values ≥ 1<<(n-1) are negative). The 64-bit escape is a raw int64 cast. Timestamps must be non-decreasing for optimal compression; decreasing timestamps still round-trip but produce 68-bit escapes.

func EncodeU128

func EncodeU128(dst []byte, vals []U128) []byte

EncodeU128 appends a run-length-encoded U128 column to dst (CodecID128). The id sort key of a metric part is long runs of one id (all of a series' samples are contiguous), so RLE stores a distinct id + run length per run — far smaller than storing every row.

Layout: [uvarint rows] then per run [u128 id big-endian][uvarint runLength].

func EncodeU128Runs added in v0.37.0

func EncodeU128Runs(dst []byte, runs []U128Run) []byte

EncodeU128Runs is EncodeU128 over an already run-length-encoded column, so a writer producing its rows a run at a time never materializes the expanded []U128 just to have the encoder collapse it again. Zero-count runs are skipped and adjacent equal runs coalesced, so the output is byte-identical to EncodeU128 over the expanded column.

func IsEOF

func IsEOF(err error) bool

IsEOF reports whether err is an end-of-stream error.

Types

type Codec

type Codec uint8

Codec identifies a column encoding (DESIGN.md §6, §14 M0). It is stored in the column/part metadata so the decoder selects the right [Decode] function. Values are stable (persisted/wire-stable); never reorder.

const (
	// CodecNone is the identity codec (raw values, no compression).
	CodecNone Codec = iota
	// CodecDoD is delta-of-delta for timestamps (Prometheus-style, ms-resolution
	// buckets 14/17/20/64). ~0 bits/sample at constant scrape interval.
	CodecDoD
	// CodecGorilla is Gorilla XOR for float64 values. ~1 bit/sample when consecutive
	// float values share leading/trailing zero structure.
	CodecGorilla
	// CodecDict is dictionary encoding for low-cardinality strings (≤256 distinct →
	// 1 byte/row).
	CodecDict
	// CodecT64 is ClickHouse T64: bit-transpose + crop for low-range int64 values.
	// Lossless; crops unused high bits, transposes 64-wide blocks.
	CodecT64
	// CodecDecimal is VictoriaMetrics-style scaled-decimal + nearest-delta for
	// float64. Optionally lossy (precisionBits < 64): zeros trailing low bits of
	// deltas so the varint stream is ZSTD-compressible.
	CodecDecimal
	// CodecID128 is run-length encoding for 128-bit id columns ([U128]): a sorted id
	// column (e.g. the SeriesID sort key of a metric part) is long runs of one id, so
	// RLE stores a distinct id + run length per run.
	CodecID128
	// CodecBytesRaw stores byte-string columns with no dictionary: a fixed-width block
	// (one shared length + values back-to-back) when every value is the same length, else
	// length-prefixed inline values. It is the right choice for high-cardinality, near-unique
	// id columns (e.g. a span id) where a dictionary is pure overhead. The decoder reads the
	// self-describing flag in the stream, so [DecodeBytes]/[DecodeBytesDict] handle it without
	// consulting the codec.
	CodecBytesRaw
)

func (Codec) String

func (c Codec) String() string

String returns a stable lower-case codec name.

type DecimalDecoder added in v0.15.0

type DecimalDecoder struct {
	// contains filtered or unexported fields
}

DecimalDecoder is a forward cursor over a scaled-decimal + nearest-delta encoded float64 column (EncodeFloatsDecimal).

func NewDecimalDecoder added in v0.15.0

func NewDecimalDecoder(src []byte) (*DecimalDecoder, error)

NewDecimalDecoder parses the column header and returns a cursor over its rows.

func (*DecimalDecoder) Len added in v0.15.0

func (d *DecimalDecoder) Len() int

Len returns the column's total row count.

func (*DecimalDecoder) Next added in v0.15.0

func (d *DecimalDecoder) Next() (float64, error)

Next decodes and returns the next value. It returns an IsEOF error after the last row.

func (*DecimalDecoder) Pos added in v0.15.0

func (d *DecimalDecoder) Pos() int

Pos returns the number of rows already decoded.

type DictColumn

type DictColumn struct {
	// Entries holds the unique values, indexed by id. In the flat-fallback form
	// (IDWidth == 0) it instead holds one value per row, indexed directly by row.
	Entries [][]byte
	// IDs is the raw row-id array as stored: IDWidth bytes per row, big-endian. It is
	// nil when IDWidth == 0.
	IDs []byte
	// IDWidth is the number of id bytes per row: 1 (dict ≤ 256 entries), 2 (larger
	// dict), or 0 for the flat fallback where Entries is indexed by row directly.
	IDWidth int
}

DictColumn is a decoded dictionary column in its split form: the unique entries plus the raw per-row id array, without the gather that materializes one []byte slice header per row. It is the output of DecodeBytesDict.

Profiling (see git history of the dict codec) showed 82% of DecodeBytes time was the gather loop `dst[i] = entries[idBuf[i]]`, which is pure store bandwidth and cannot be sped up in place. The split form defers that work to DictColumn.At, so a query that filters most rows on their id before projecting pays the gather only for surviving rows (DESIGN.md §7 fetch contract: decode only what the query touches).

All byte slices alias the source passed to the decode; they are valid only until that source is mutated or released. A DictColumn must not be retained past its source.

func DecodeBytesDict

func DecodeBytesDict(src []byte) (*DictColumn, int, error)

DecodeBytesDict decodes a dictionary-encoded column (as written by EncodeBytes or DictEncoder.Encode) into its split form without gathering per-row values. It returns the column, the number of source bytes consumed, and any error. The returned DictColumn and all its byte slices alias src.

This allocates a fresh DictColumn; to decode repeatedly with zero allocations, reuse one column via DictColumn.DecodeBytes.

func (*DictColumn) At

func (c *DictColumn) At(row int) []byte

At returns the value at row, as a view aliasing the decode source. row must be in [0, Len()).

func (*DictColumn) DecodeBytes

func (c *DictColumn) DecodeBytes(src []byte) (int, error)

DecodeBytes decodes a dictionary-encoded column from src into c, reusing c's Entries backing array. It returns the number of source bytes consumed and any error. The decoded byte slices alias src.

func (*DictColumn) Len

func (c *DictColumn) Len() int

Len reports the number of rows in the column. It is derived from the fields so a DictColumn can be constructed directly (e.g. a constant column: one entry, an all-zero IDs slice of the desired length, IDWidth 1).

type DictEncoder

type DictEncoder struct {
	// contains filtered or unexported fields
}

DictEncoder is a reusable dictionary-column encoder. Unlike the standalone EncodeBytes, it owns its pool.ByteIntMap and scratch slices for the lifetime of the encoder, so a sequence of DictEncoder.Encode calls keeps the hash table and id arrays cache-warm and skips the per-call sync.Pool Get/Put.

It is intended for the write path, where one goroutine encodes many column batches in a row. The zero value is not usable; create one with NewDictEncoder. Not safe for concurrent use; pool one per goroutine.

func NewDictEncoder

func NewDictEncoder() *DictEncoder

NewDictEncoder returns a DictEncoder with a warm, empty hash table.

func (*DictEncoder) Encode

func (e *DictEncoder) Encode(dst []byte, vals [][]byte) []byte

Encode appends a dictionary-encoded column for vals to dst and returns the extended slice. The output is byte-identical to EncodeBytes for the same input. Each call resets the encoder's internal state first, so Encode is self-contained.

func (*DictEncoder) Release

func (e *DictEncoder) Release()

Release returns the encoder's hash table to the shared pool. After Release the encoder must not be used. Use it when an encoder's lifetime ends so the map can be reused by [NewByteIntMap]/EncodeBytes.

func (*DictEncoder) Reset

func (e *DictEncoder) Reset()

Reset clears the encoder's retained state without freeing its backing arrays, so the next DictEncoder.Encode starts from a clean, cache-warm encoder. Encode resets implicitly, so calling Reset is only needed to drop references to a prior batch's input values held in the entries slice.

type DictMerger added in v0.37.0

type DictMerger struct {
	// contains filtered or unexported fields
}

DictMerger accumulates the decoded granules of a block-framed bytes column into one DictColumn spanning their rows.

A block-framed bytes column encodes each granule independently, so each carries its own dictionary and its ids mean nothing outside it. A reader that decodes several granules must therefore remap them into a shared dictionary — a column of concatenated per-granule dictionaries is not a DictColumn, and handing the query engine one column per granule would push the per-granule structure into every caller.

Merging rather than flattening is what preserves the per-distinct-entry predicate memo: with a dictionary, a regex or attribute lookup is evaluated once per distinct value; without one it runs per row. That memo is the reason a low-cardinality column is worth dictionary-encoding at all, so a merge that flattened would give back most of what the encoding bought.

The merged dictionary degrades to the flat form (one entry per row, IDWidth 0) as soon as it cannot pay: a source granule that is itself flat, or a merged dictionary past the 2-byte id width. That mirrors what the encoder does within one granule, so the merged column is always a shape DictColumn.At already handles.

func (*DictMerger) Append added in v0.37.0

func (d *DictMerger) Append(c *DictColumn)

Append adds every row of c to the merge. The byte slices of c are retained, not copied, so the caller must keep c's backing buffer alive until DictMerger.Build — for a block-framed column that means the decompressed frames must not be recycled underneath the walk.

func (*DictMerger) AppendAt added in v0.37.0

func (d *DictMerger) AppendAt(c *DictColumn, off int)

AppendAt adds every row of c to the merge, landing at row offset off. Scatter mode only.

func (*DictMerger) AppendShared added in v0.38.0

func (d *DictMerger) AppendShared(ids []byte, idWidth, rows int)

AppendShared adds rows of a granule encoded as ids into the dictionary given to DictMerger.SeedShared. ids is the granule's packed big-endian id array at idWidth bytes per row; every id must be within the seeded dictionary, which the caller validates.

func (*DictMerger) AppendSharedAt added in v0.38.0

func (d *DictMerger) AppendSharedAt(ids []byte, idWidth, rows, off int)

AppendSharedAt is DictMerger.AppendShared landing at row offset off. Scatter mode only.

func (*DictMerger) Build added in v0.37.0

func (d *DictMerger) Build() *DictColumn

Build returns the merged column. Its byte slices alias those of the appended granules.

func (*DictMerger) Reset added in v0.37.0

func (d *DictMerger) Reset()

Reset returns m to its empty state, keeping its buffers for reuse.

func (*DictMerger) Scatter added in v0.37.0

func (d *DictMerger) Scatter(rows int)

Scatter puts the merge in whole-column mode: the result spans the column, and each appended granule lands at its own offset rather than being packed against its predecessor. Rows no granule covers hold an unspecified value — the caller reads only the rows it selected.

This is what lets a pruned read keep working in *part row indices*. A packed result would renumber every row a query already located through the part's row-range index and its marks, so every caller would have to translate; the int64 path avoids that by decoding into the destination at absolute offsets, and this gives bytes columns the same property. The cost is an id array sized to the column rather than to the selection — one or two bytes per skipped row, against the values those rows would otherwise have decoded.

func (*DictMerger) SeedShared added in v0.38.0

func (d *DictMerger) SeedShared(entries [][]byte)

SeedShared registers a column-wide dictionary, remapping its entries into the merge once so that every granule encoded against it costs an id lookup per row and no hashing at all. Idempotent: only the first call for a merge does the work.

This is what keeps a column that mixes both granule modes off a cliff. Without it, a granule carrying the shared dictionary as its own reaches DictMerger.Append, which hashes every entry of it — so a column with one self-encoded granule paid granules x sharedEntries probes (measured: 2.4M for a 40-granule, 60509-entry attributes column, against zero for the same column with no self-encoded granule).

Call it before appending the first shared granule, not at the start of the merge: seeding assigns ids, so seeding a selection that turns out to hold no shared granule would put unreferenced entries in the merged dictionary.

type FloatDecoder added in v0.15.0

type FloatDecoder interface {
	Len() int
	Pos() int
	Next() (float64, error)
}

FloatDecoder is the forward-cursor interface over a float64 column, regardless of codec.

func NewConstFloatDecoder added in v0.15.0

func NewConstFloatDecoder(n int, value float64) FloatDecoder

NewConstFloatDecoder returns a cursor that yields value for n rows.

func NewFloatDecoder added in v0.15.0

func NewFloatDecoder(codec Codec, src []byte) (FloatDecoder, error)

NewFloatDecoder returns a forward cursor over a float64 column encoded with codec, or an error if codec is not a float codec (CodecGorilla, CodecDecimal).

type GorillaDecoder added in v0.15.0

type GorillaDecoder struct {
	// contains filtered or unexported fields
}

GorillaDecoder is a forward cursor over a Gorilla XOR encoded float64 column (EncodeFloats).

func NewGorillaDecoder added in v0.15.0

func NewGorillaDecoder(src []byte) (*GorillaDecoder, error)

NewGorillaDecoder parses the column header and returns a cursor over its rows.

func (*GorillaDecoder) Len added in v0.15.0

func (d *GorillaDecoder) Len() int

Len returns the column's total row count.

func (*GorillaDecoder) Next added in v0.15.0

func (d *GorillaDecoder) Next() (float64, error)

Next decodes and returns the next value. It returns an IsEOF error after the last row.

func (*GorillaDecoder) Pos added in v0.15.0

func (d *GorillaDecoder) Pos() int

Pos returns the number of rows already decoded.

type TsCursor added in v0.15.0

type TsCursor interface {
	Len() int
	Pos() int
	Next() (int64, error)
}

TsCursor is the forward-cursor interface over an int64 timestamp column (CodecDoD).

func NewConstTsCursor added in v0.15.0

func NewConstTsCursor(n int, value int64) TsCursor

NewConstTsCursor returns a cursor that yields value for n rows.

type TsDecoder added in v0.15.0

type TsDecoder struct {
	// contains filtered or unexported fields
}

TsDecoder is a forward cursor over a delta-of-delta encoded timestamp column (EncodeTimestamps).

func NewTsDecoder added in v0.15.0

func NewTsDecoder(src []byte) (*TsDecoder, error)

NewTsDecoder parses the column header and returns a cursor over its rows. bound is the byte length of the column stream (header + payload), used to bound-check the row count.

func (*TsDecoder) Len added in v0.15.0

func (d *TsDecoder) Len() int

Len returns the column's total row count.

func (*TsDecoder) Next added in v0.15.0

func (d *TsDecoder) Next() (int64, error)

Next decodes and returns the next timestamp. It returns an IsEOF error after the last row.

func (*TsDecoder) Pos added in v0.15.0

func (d *TsDecoder) Pos() int

Pos returns the number of rows already decoded.

type U128

type U128 struct {
	Hi, Lo uint64
}

U128 is an unsigned 128-bit value (a SeriesID at the storage boundary). Comparable, so runs of equal ids are detected directly.

func DecodeU128

func DecodeU128(dst []U128, src []byte) ([]U128, int, error)

DecodeU128 decodes a U128 column into dst (reusing its capacity), returning the result and bytes consumed.

type U128Run added in v0.37.0

type U128Run struct {
	Value U128
	Count int
}

U128Run is one run of a run-length-encoded U128 column: a value repeated Count times.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL