recordlayer

package
v0.0.0-...-86ddd85 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2026 License: Apache-2.0 Imports: 51 Imported by: 0

Documentation

Index

Constants

View Source
const (
	FunctionNameCount        = "count"
	FunctionNameCountNotNull = "count_not_null"
	FunctionNameCountUpdates = "count_updates"
	FunctionNameSum          = "sum"
	FunctionNameMinEver      = "min_ever"
	FunctionNameMaxEver      = "max_ever"
	FunctionNameMin          = "min"
	FunctionNameMax          = "max"

	// RANK aggregate function names.
	FunctionNameRankForScore         = "rank_for_score"
	FunctionNameScoreForRank         = "score_for_rank"
	FunctionNameScoreForRankElseSkip = "score_for_rank_else_skip"
	FunctionNameCountDistinct        = "count_distinct"

	// BITMAP_VALUE aggregate function name.
	FunctionNameBitmapValue = "bitmap_value"
)

Aggregate function name constants matching Java's FunctionNames.

View Source
const (
	CollateFuncJRE = "collate_jre"
	CollateFuncICU = "collate_icu"
)

Collation function names matching Java's CollateFunctionKeyExpressionFactory. Both JRE and ICU variants are registered since Go uses golang.org/x/text/collate (CLDR-based, similar to ICU).

NOTE: Collation key bytes are NOT wire-compatible with Java's. Java uses java.text.CollationKey.toByteArray() (JRE) or com.ibm.icu.text.CollationKey.toByteArray() (ICU), whose binary formats are Java/ICU-version-specific. Go's collation keys use golang.org/x/text's CLDR-based format. This means: - Go can read/write its own collated indexes correctly - Go preserves collated index definitions during metadata round-trip - Go CANNOT share collated indexes with Java (different sort key bytes)

View Source
const (
	CollateStrengthPrimary   = 0 // Base form only (ignores case and accents)
	CollateStrengthSecondary = 1 // Base form + accents (case-insensitive)
	CollateStrengthTertiary  = 2 // Base form + accents + case
)

Collation strength levels matching Java's Collator.PRIMARY/SECONDARY/TERTIARY.

View Source
const (
	// StoreInfoKey is the subspace key for store metadata
	StoreInfoKey = 0

	// RecordKey is the subspace key for storing records
	RecordKey = 1

	// IndexKey is the subspace key for storing indexes
	IndexKey = 2

	// IndexSecondarySpaceKey is the subspace key for secondary index data
	IndexSecondarySpaceKey = 3

	// RecordCountKey is the subspace key for record counts
	RecordCountKey = 4

	// IndexStateSpaceKey is the subspace key for index state
	IndexStateSpaceKey = 5

	// IndexRangeSpaceKey is the subspace key for index ranges
	IndexRangeSpaceKey = 6

	// IndexUniquenessViolationsKey is the subspace key for uniqueness violations
	IndexUniquenessViolationsKey = 7

	// RecordVersionKey is the subspace key for record versions
	RecordVersionKey = 8

	// IndexBuildSpaceKey is the subspace key for index building
	IndexBuildSpaceKey = 9
)

Subspace keys used by the Record Layer to organize data within FDB. These MUST match the Java implementation for compatibility. Verified against Java: FDBRecordStoreKeyspace.java (enum values 0-9)

View Source
const (
	IndexTypeValue                 = "value"
	IndexTypeCount                 = "count"
	IndexTypeCountNotNull          = "count_not_null"
	IndexTypeCountUpdates          = "count_updates"
	IndexTypeSum                   = "sum"
	IndexTypeMaxEverLong           = "max_ever_long"
	IndexTypeMinEverLong           = "min_ever_long"
	IndexTypeMaxEverTuple          = "max_ever_tuple"
	IndexTypeMinEverTuple          = "min_ever_tuple"
	IndexTypeRank                  = "rank"
	IndexTypeVersion               = "version"
	IndexTypeMaxEverVersion        = "max_ever_version"
	IndexTypePermutedMin           = "permuted_min"
	IndexTypePermutedMax           = "permuted_max"
	IndexTypeBitmapValue           = "bitmap_value"
	IndexTypeText                  = "text"
	IndexTypeTimeWindowLeaderboard = "time_window_leaderboard"
	IndexTypeMultidimensional      = "multidimensional"
	IndexTypeVector                = "vector"
	// IndexTypeVectorSPFresh is the Go-only FDB-native vector index (RFC-094):
	// SPANN centroid + posting-list layout with two-level routing and SPFresh
	// incremental rebalancing. Java has no counterpart; deployments sharing
	// metadata with Java apps must keep this index out of shared metadata (a
	// Java app fails maintainer lookup for the unknown type). Records remain
	// fully Java-readable — the index writes only under its own subspace.
	IndexTypeVectorSPFresh = "vector_spfresh"
)

Index type constants matching Java's IndexTypes.

View Source
const (
	IndexOptionUnique               = "unique"
	IndexOptionClearWhenZero        = "clearWhenZero"
	IndexOptionReplacedByPrefix     = "replacedBy"
	IndexOptionBitmapValueEntrySize = "bitmapValueEntrySize"

	// TEXT index options matching Java's IndexOptions.
	IndexOptionTextTokenizerName               = "textTokenizerName"
	IndexOptionTextTokenizerVersion            = "textTokenizerVersion"
	IndexOptionTextAddAggressiveConflictRanges = "textAddAggressiveConflictRanges"
	IndexOptionTextOmitPositions               = "textOmitPositions"

	// Runtime-only index option, always safe to change.
	// Matches Java's IndexOptions.ALLOWED_FOR_QUERY_OPTION.
	IndexOptionAllowedForQuery = "allowedForQuery"
)

Index option keys matching Java's IndexOptions.

View Source
const (
	IndexOptionRTreeMaxM   = "rtreeMaximumM"
	IndexOptionRTreeMinM   = "rtreeMinimumM"
	IndexOptionRTreeSplitS = "rtreeSplitS"

	// IndexOptionRTreeStorage controls the node storage strategy.
	// Matches Java's IndexOptions.RTREE_STORAGE.
	IndexOptionRTreeStorage = "rtreeStorage"

	// IndexOptionRTreeStoreHilbertValues controls whether Hilbert values are stored.
	// Matches Java's IndexOptions.RTREE_STORE_HILBERT_VALUES.
	IndexOptionRTreeStoreHilbertValues = "rtreeStoreHilbertValues"

	// IndexOptionRTreeUseNodeSlotIndex controls whether a node slot index is maintained.
	// Matches Java's IndexOptions.RTREE_USE_NODE_SLOT_INDEX.
	IndexOptionRTreeUseNodeSlotIndex = "rtreeUseNodeSlotIndex"
)

R-tree index option keys for configuring the Hilbert R-tree.

View Source
const (
	OrderFuncAscNullsFirst  = "order_asc_nulls_first"
	OrderFuncAscNullsLast   = "order_asc_nulls_last"
	OrderFuncDescNullsFirst = "order_desc_nulls_first"
	OrderFuncDescNullsLast  = "order_desc_nulls_last"
)

Order function names matching Java's OrderFunctionKeyExpressionFactory. Each name maps to a TupleOrdering.Direction encoding strategy.

View Source
const (
	IndexOptionRankNLevels         = "rankNLevels"
	IndexOptionRankHashFunction    = "rankHashFunction"
	IndexOptionRankCountDuplicates = "rankCountDuplicates"
)

Index option keys for RANK indexes. Matches Java's IndexOptions.RANK_*.

View Source
const (
	FunctionNameRank                   = "rank"
	FunctionNameTimeWindowRank         = "time_window_rank"
	FunctionNameTimeWindowRankAndEntry = "time_window_rank_and_entry"
)

Record function name constants matching Java's FunctionNames.

View Source
const (
	// VersionBytes is the total size of a record version.
	VersionBytes = 12
	// GlobalVersionBytes is the size of the FDB versionstamp portion.
	GlobalVersionBytes = 10
	// LocalVersionBytes is the size of the local version counter.
	LocalVersionBytes = 2
)
View Source
const (
	// IsolationLevelSnapshot uses snapshot reads, which see a consistent view of the database
	// at the time the transaction started. Snapshot reads do not conflict with writes.
	//
	// Java equivalent: SNAPSHOT
	IsolationLevelSnapshot IsolationLevel = iota

	// IsolationLevelSerializable uses serializable reads, which participate in conflict detection.
	// Serializable reads will cause conflicts if another transaction writes to the same keys.
	//
	// Java equivalent: SERIALIZABLE
	IsolationLevelSerializable

	// Legacy aliases for backwards compatibility
	SnapshotIsolation     = IsolationLevelSnapshot
	SerializableIsolation = IsolationLevelSerializable
)
View Source
const (
	// IndexOptionSPFreshNumDimensions is the vector dimensionality. Required.
	IndexOptionSPFreshNumDimensions = "spfreshNumDimensions"
	// IndexOptionSPFreshMetric is the distance metric (EUCLIDEAN_METRIC,
	// COSINE_METRIC, DOT_PRODUCT_METRIC — same names the HNSW index accepts).
	IndexOptionSPFreshMetric = "spfreshMetric"
	// IndexOptionSPFreshLmax is the posting-list split threshold in entries.
	// Sized so one posting fits a single range-reply (REPLY_BYTE_LIMIT = 80 KB).
	IndexOptionSPFreshLmax = "spfreshLmax"
	// IndexOptionSPFreshLminRatio divides Lmax to produce the merge threshold.
	IndexOptionSPFreshLminRatio = "spfreshLminRatio"
	// IndexOptionSPFreshCellTarget is the fine-centroids-per-cell build target;
	// sized so one L2 cell load fits a single range-reply.
	IndexOptionSPFreshCellTarget = "spfreshCellTarget"
	// IndexOptionSPFreshCellMax is the coarse-split threshold in fine centroids.
	IndexOptionSPFreshCellMax = "spfreshCellMax"
	// IndexOptionSPFreshReplication is the closure replication cap r.
	IndexOptionSPFreshReplication = "spfreshReplication"
	// IndexOptionSPFreshAlpha is the RNG closure threshold: keep centroid c_i of
	// the r nearest iff dist(v,c_i) <= alpha * dist(v,c_1). Must be > 1.0 or
	// only the nearest centroid is ever admitted (effective r=1).
	IndexOptionSPFreshAlpha = "spfreshAlpha"
	// IndexOptionSPFreshKn is the NPA reassignment neighborhood (centroids).
	IndexOptionSPFreshKn = "spfreshKn"
	// IndexOptionSPFreshBuildAssignCells is the bulk-build wave-B assignment
	// width w_b (RFC-099): how many nearest coarse cells supply candidate fine
	// centroids when assigning an imported vector. Build-time only — it changes
	// which fine a vector is assigned to, never the on-disk format. Must be ≥
	// the query probe width so build assignments are query-reachable.
	IndexOptionSPFreshBuildAssignCells = "spfreshBuildAssignCells"
	// IndexOptionSPFreshCooldownSec is the post-split merge cooldown.
	IndexOptionSPFreshCooldownSec = "spfreshCooldownSec"
	// IndexOptionSPFreshRaBitQNumExBits is the RaBitQ extended-bits parameter
	// for posting residual codes.
	IndexOptionSPFreshRaBitQNumExBits = "spfreshRaBitQNumExBits"
	// IndexOptionSPFreshSidecar enables the fp16 SIDECAR subspace. Default
	// true — and currently REQUIRED: the sidecar is not just the query
	// re-rank source, every rebalancer lifecycle reads it (split 2-means,
	// chunked drain, merge drain, GC re-home), so disabling it would brick
	// maintenance permanently. ValidateSPFreshConfig rejects false until a
	// source-record fallback exists for all of those paths. The option stays
	// (the wire layout reserves the choice); only the value is constrained.
	IndexOptionSPFreshSidecar = "spfreshSidecar"
)

SPFresh index options (RFC-094 §10). All structural options are immutable for an existing index — enforced by the metadata-evolution validator — because the lifecycle invariants (topology, posting sizes, closure replication) are derived from them. Runtime knobs (probe width w, k_c, ε, re-rank C, refresh interval, rebalancer pacing) are deliberately NOT index options: they are query/maintenance-time parameters and are never stored.

View Source
const (
	FunctionNameTimeWindowCount                = "time_window_count"
	FunctionNameScoreForTimeWindowRank         = "score_for_time_window_rank"
	FunctionNameScoreForTimeWindowRankElseSkip = "score_for_time_window_rank_else_skip"
	FunctionNameTimeWindowRankForScore         = "time_window_rank_for_score"
)

Aggregate function name constants for TIME_WINDOW_LEADERBOARD.

View Source
const AllTimeLeaderboardType = 0

AllTimeLeaderboardType is the type value for the all-time leaderboard. Matches Java's TimeWindowLeaderboard.ALL_TIME_LEADERBOARD_TYPE.

View Source
const DefaultMaterializationLimit = 100_000
View Source
const DefaultTextTokenizerName = "default"

DefaultTextTokenizerName is the name of the default tokenizer.

View Source
const FunctionNameCardinality = "cardinality"

FunctionNameCardinality is the registry name for the CARDINALITY() key expression. Matches Java's FunctionNames.CARDINALITY ("cardinality") byte for byte — the proto Function.name written for a cardinality-keyed index is identical across engines, so a Go-written cardinality index round-trips wire-compatibly with Java.

View Source
const (
	FunctionNameVersion = "version"
)

Store function name constants matching Java's FunctionNames.

View Source
const GlobalMinVersion = 0

GlobalMinVersion is the absolute minimum tokenizer version. All tokenizers should begin at this version. Matches Java's TextTokenizer.GLOBAL_MIN_VERSION.

View Source
const IndexOptionHNSWEfConstruction = "hnswEfConstruction"

IndexOptionHNSWEfConstruction specifies the search factor used during index construction. Matches Java's IndexOptions.HNSW_EF_CONSTRUCTION.

View Source
const IndexOptionHNSWEfRepair = "hnswEfRepair"

IndexOptionHNSWEfRepair specifies the search factor used during repair operations. Matches Java's IndexOptions.HNSW_EF_REPAIR.

View Source
const IndexOptionHNSWM = "hnswM"

IndexOptionHNSWM specifies the connectivity factor M for the HNSW graph. Matches Java's IndexOptions.HNSW_M.

View Source
const IndexOptionHNSWMMax = "hnswMMax"

IndexOptionHNSWMMax specifies the maximum number of connections for non-zero layers. Matches Java's IndexOptions.HNSW_M_MAX.

View Source
const IndexOptionHNSWMMax0 = "hnswMMax0"

IndexOptionHNSWMMax0 specifies the maximum number of connections for layer 0. Matches Java's IndexOptions.HNSW_M_MAX_0.

View Source
const IndexOptionHNSWMaintainStatsProbability = "hnswMaintainStatsProbability"

IndexOptionHNSWMaintainStatsProbability controls the probability of maintaining stats. Runtime-only option, safe to change without rebuild. Matches Java's IndexOptions.HNSW_MAINTAIN_STATS_PROBABILITY.

View Source
const IndexOptionHNSWMaxNumConcurrentDeleteFromLayer = "hnswMaxNumConcurrentDeleteFromLayer"

IndexOptionHNSWMaxNumConcurrentDeleteFromLayer controls the maximum number of concurrent layer deletions during deletion of a record. Stored for Java round-trip compatibility. Matches Java's IndexOptions.HNSW_MAX_NUM_CONCURRENT_DELETE_FROM_LAYER.

View Source
const IndexOptionHNSWMaxNumConcurrentNeighborhoodFetches = "hnswMaxNumConcurrentNeighborhoodFetches"

IndexOptionHNSWMaxNumConcurrentNeighborhoodFetches controls the maximum number of concurrent neighborhood fetches during insert when neighbors are pruned. Stored for Java round-trip compatibility. Matches Java's IndexOptions.HNSW_MAX_NUM_CONCURRENT_NEIGHBORHOOD_FETCHES.

View Source
const IndexOptionHNSWMaxNumConcurrentNodeFetches = "hnswMaxNumConcurrentNodeFetches"

IndexOptionHNSWMaxNumConcurrentNodeFetches controls the maximum number of concurrent node fetches during search and modification operations. In Go's synchronous model this is not used for concurrency control, but is stored for Java round-trip compatibility. Matches Java's IndexOptions.HNSW_MAX_NUM_CONCURRENT_NODE_FETCHES.

View Source
const IndexOptionHNSWRaBitQNumExBits = "hnswRaBitQNumExBits"

IndexOptionHNSWRaBitQNumExBits specifies the number of extra bits for RaBitQ. Matches Java's IndexOptions.HNSW_RABITQ_NUM_EX_BITS.

View Source
const IndexOptionHNSWSampleVectorStatsProbability = "hnswSampleVectorStatsProbability"

IndexOptionHNSWSampleVectorStatsProbability controls the probability of sampling vector stats. Runtime-only option, safe to change without rebuild. Matches Java's IndexOptions.HNSW_SAMPLE_VECTOR_STATS_PROBABILITY.

View Source
const IndexOptionHNSWStatsThreshold = "hnswStatsThreshold"

IndexOptionHNSWStatsThreshold specifies the minimum number of vectors for stats. Runtime-only option, safe to change without rebuild. Matches Java's IndexOptions.HNSW_STATS_THRESHOLD.

View Source
const IndexOptionHNSWUseInlining = "hnswUseInlining"

IndexOptionHNSWUseInlining controls whether vector data is inlined into the HNSW node. Matches Java's IndexOptions.HNSW_USE_INLINING.

View Source
const IndexOptionHNSWUseRaBitQ = "hnswUseRaBitQ"

IndexOptionHNSWUseRaBitQ enables RaBitQ quantization for approximate nearest neighbor. Matches Java's IndexOptions.HNSW_USE_RABITQ.

View Source
const IndexOptionPermutedSize = "permutedSize"

IndexOptionPermutedSize specifies how many trailing grouping fields are permuted to after the value in the secondary index subspace. Matches Java's IndexOptions.PERMUTED_SIZE_OPTION.

View Source
const IndexOptionVectorExtendCandidates = "hnswExtendCandidates"

IndexOptionVectorExtendCandidates controls whether the candidate set is extended with neighbors-of-neighbors during neighbor selection (2nd-degree exploration). Matches Java's IndexOptions.HNSW_EXTEND_CANDIDATES.

View Source
const IndexOptionVectorKeepPrunedConnections = "hnswKeepPrunedConnections"

IndexOptionVectorKeepPrunedConnections controls whether pruned candidates are added back to fill up to M neighbors when the heuristic selection produces too few. Matches Java's IndexOptions.HNSW_KEEP_PRUNED_CONNECTIONS.

View Source
const IndexOptionVectorMetric = "hnswMetric"

IndexOptionVectorMetric specifies the distance metric. Matches Java's IndexOptions.HNSW_METRIC.

View Source
const IndexOptionVectorNumDimensions = "hnswNumDimensions"

IndexOptionVectorNumDimensions specifies the number of vector dimensions. Matches Java's IndexOptions.HNSW_NUM_DIMENSIONS.

Variables

View Source
var (
	// Query path.
	EventSPFreshSearch = Event{"spfresh_search", "SPFresh Search"}
	// Probed/pruned: the Eq.(3) pruning decomposition per search — probed
	// lists cost range reads, pruned ones were skipped.
	CountSPFreshPostingsProbed  = Event{"spfresh_postings_probed", "SPFresh Postings Probed"}
	CountSPFreshPostingsPruned  = Event{"spfresh_postings_pruned", "SPFresh Postings Pruned"}
	CountSPFreshEntriesScanned  = Event{"spfresh_entries_scanned", "SPFresh Entries Scanned"}
	CountSPFreshRerankReads     = Event{"spfresh_rerank_reads", "SPFresh Rerank Reads"}
	CountSPFreshStarvationWiden = Event{"spfresh_starvation_widenings", "SPFresh Starvation Widenings"}
	CountSPFreshForwardFollows  = Event{"spfresh_forward_follows", "SPFresh Forward Follows"}
	// Phase 2 reached: the VBASE relaxed-monotonicity termination (M_q^s > R_q)
	// latched during a one-shot search's traversal — the recently-traversed cells
	// no longer beat the running k-th best (RFC-156 Phase A). PURE TELEMETRY on
	// the one-shot wrapper path: nothing consults f.phase2 as a stop signal (it
	// does not truncate the exact horizon). The resumable Phase B/C streaming
	// cursor does NOT consult phase2 — it terminates on the relaxed-monotonicity
	// EMISSION BARRIER plus the budget/exhaustion caps (spfresh_stream.go), and
	// it never calls refreshPhase2, so this counter NEVER increments on a streaming
	// query (the SHARED searchInit probe still feeds observe(), but the streaming
	// WIDEN bursts gate it off — scoreCells, f.reranked==nil — since those queues
	// are dead weight once nothing will read phase2).
	CountSPFreshPhase2Reached = Event{"spfresh_phase2_reached", "SPFresh Phase 2 Reached"}
	// Capped posting reads: a search's posting fetch returned exactly the
	// 4×Lmax+1 cap — the posting is PAST the split-dispatch envelope and its
	// tail is invisible to queries. Nonzero means a split trigger was lost
	// (the read path re-files it; see CountSPFreshReadPathSplitFiles).
	CountSPFreshCappedPostingReads = Event{"spfresh_capped_posting_reads", "SPFresh Capped Posting Reads"}
	// Split tasks re-filed from the read path after a capped read found an
	// over-envelope posting with no pending split.
	CountSPFreshReadPathSplitFiles = Event{"spfresh_readpath_split_files", "SPFresh Read-Path Split Files"}
	// Stream widen batches: each demand-driven widening step of the RFC-156
	// Phase C ordered-stream cursor (a batch of ε-pruned/re-routed cells admitted
	// in d2 order because the consumer above drained the finalized prefix and
	// pulled for more). Batched, never one-cell-serial.
	CountSPFreshStreamWiden = Event{"spfresh_stream_widenings", "SPFresh Stream Widenings"}
	// Filtered truncation: the RFC-156 Phase C ordered-stream cursor hit its
	// budget cap (max cells probed / max candidates) BEFORE the consumer was
	// satisfied, and returned NoNextReason.ScanLimitReached + a positional
	// continuation rather than a silent < k. This is telemetry IN ADDITION to the
	// reason (RFC-156 §C) — the reason is the contract, this counts
	// how often the budget bound a filtered KNN.
	CountSPFreshFilteredTruncated = Event{"spfresh_filtered_truncated", "SPFresh Filtered Truncations"}

	// Write path.
	EventSPFreshInsert           = Event{"spfresh_insert", "SPFresh Insert"}
	CountSPFreshInsertFenceReads = Event{"spfresh_insert_fence_reads", "SPFresh Insert Fence Reads"}
	CountSPFreshInsertReplicas   = Event{"spfresh_insert_replicas", "SPFresh Insert Replicas"}
	CountSPFreshStaleRouteRetry  = Event{"spfresh_stale_route_retries", "SPFresh Stale Route Retries"}

	// Maintenance (rebalancer / sweeper).
	CountSPFreshSplits       = Event{"spfresh_splits", "SPFresh Splits"}
	CountSPFreshMerges       = Event{"spfresh_merges", "SPFresh Merges"}
	CountSPFreshCSplits      = Event{"spfresh_csplits", "SPFresh Coarse Splits"}
	CountSPFreshNPAs         = Event{"spfresh_npas", "SPFresh NPA Reassignments"}
	CountSPFreshZombieCleans = Event{"spfresh_zombie_cleans", "SPFresh Zombie Cleanups"}
	CountSPFreshCSplitDefers = Event{"spfresh_csplit_defers", "SPFresh Coarse Split Deferrals"}
	CountSPFreshLeaseSkips   = Event{"spfresh_lease_skips", "SPFresh Lease Skips"}
	// Assignment refinement (RFC-104) fleet pass: vectors re-routed against the
	// converged topology, and tenants whose cursor wrapped a full cycle moving
	// nothing. Moves trending to zero while Converged rises = the fleet has
	// recovered ingest recall-drift and is quiescing; sustained nonzero Moves =
	// ongoing drift (e.g. a steady fast-ingest tenant) the refinement loop is
	// absorbing.
	CountSPFreshRefineMoves     = Event{"spfresh_refine_moves", "SPFresh Refinement Moves"}
	CountSPFreshRefineConverged = Event{"spfresh_refine_converged", "SPFresh Refinement Converged Tenants"}
	// Task handler errors in a rebalance pass: the pass SKIPS the failed
	// task and continues (a poisoned task at the deterministic queue head
	// must not starve everything behind it), then surfaces the joined
	// errors. Nonzero here with a stable queue depth = a poisoned task; the
	// runbook's "task queue growing" playbook keys off it.
	CountSPFreshTaskErrors = Event{"spfresh_task_errors", "SPFresh Task Errors"}
)

SPFresh instrumentation events, recorded into the context's StoreTimer — the same FDBStoreTimer idiom every other index uses (the TEXT index's InstrumentedBunchedMap is the precedent). StoreTimer methods are nil-receiver-safe, so an uninstrumented context costs one nil check per site and SPFresh internals thread the timer unconditionally.

Timed events record nanoseconds; counts record occurrences or sized quantities. These are the operator-facing signals the index needs in production: query cost decomposition (probed/pruned/scanned/reranked), write-path health (fence reads, replicas, stale-route retries), and maintenance progress (per-kind lifecycle actions, zombie cleanups, lease skips). Scrape via StoreTimer.Snapshot().

View Source
var (
	EventSaveRecord     = Event{"save_record", "Save Record"}
	EventLoadRecord     = Event{"load_record", "Load Record"}
	EventDeleteRecord   = Event{"delete_record", "Delete Record"}
	EventCommit         = Event{"commit", "Commit"}
	EventGetReadVersion = Event{"get_read_version", "Get Read Version"}
	EventScanRecords    = Event{"scan_records", "Scan Records"}
	EventScanIndex      = Event{"scan_index", "Scan Index"}
	EventOpenStore      = Event{"open_store", "Open Store"}
	EventRebuildIndex   = Event{"rebuild_index", "Rebuild Index"}
)

Standard timed events — matching Java's FDBStoreTimer.Events.

View Source
var (
	CountSaveRecordKey        = Event{"save_record_key", "Save Record Key"}
	CountSaveRecordKeyBytes   = Event{"save_record_key_bytes", "Save Record Key Bytes"}
	CountSaveRecordValueBytes = Event{"save_record_value_bytes", "Save Record Value Bytes"}
	CountDeleteRecordKey      = Event{"delete_record_key", "Delete Record Key"}
	CountDeleteRecordKeyBytes = Event{"delete_record_key_bytes", "Delete Record Key Bytes"}
	CountReads                = Event{"reads", "Reads"}
	CountWrites               = Event{"writes", "Writes"}
	CountBytesRead            = Event{"bytes_read", "Bytes Read"}
	CountBytesWritten         = Event{"bytes_written", "Bytes Written"}

	// Index-level count events — matching Java's FDBStoreTimer.Counts for index ops.
	// Used by InstrumentedBunchedMap (TEXT index) and other index maintainers.
	CountSaveIndexKey          = Event{"save_index_key", "Save Index Key"}
	CountSaveIndexKeyBytes     = Event{"save_index_key_bytes", "Save Index Key Bytes"}
	CountSaveIndexValueBytes   = Event{"save_index_value_bytes", "Save Index Value Bytes"}
	CountLoadIndexKey          = Event{"load_index_key", "Load Index Key"}
	CountLoadIndexKeyBytes     = Event{"load_index_key_bytes", "Load Index Key Bytes"}
	CountLoadIndexValueBytes   = Event{"load_index_value_bytes", "Load Index Value Bytes"}
	CountDeleteIndexKey        = Event{"delete_index_key", "Delete Index Key"}
	CountDeleteIndexKeyBytes   = Event{"delete_index_key_bytes", "Delete Index Key Bytes"}
	CountDeleteIndexValueBytes = Event{"delete_index_value_bytes", "Delete Index Value Bytes"}
)

Standard count events — matching Java's FDBStoreTimer.Counts.

View Source
var (
	// OrderAscNullsFirst: ascending order, nulls sort first (default tuple behavior).
	OrderAscNullsFirst = OrderDirection{/* contains filtered or unexported fields */}
	// OrderAscNullsLast: ascending order, nulls sort last (0xFE encoding).
	OrderAscNullsLast = OrderDirection{/* contains filtered or unexported fields */}
	// OrderDescNullsFirst: descending order, nulls sort first.
	OrderDescNullsFirst = OrderDirection{/* contains filtered or unexported fields */}
	// OrderDescNullsLast: descending order, nulls sort last.
	OrderDescNullsLast = OrderDirection{/* contains filtered or unexported fields */}
)

The four order directions matching Java's TupleOrdering.Direction enum values.

View Source
var TupleRangeAll = TupleRange{
	LowEndpoint:  EndpointTypeTreeStart,
	HighEndpoint: EndpointTypeTreeEnd,
}

TupleRangeAll covers all entries in the index. Matches Java's TupleRange.ALL.

Functions

func AsList

func AsList[T any](ctx context.Context, cursor RecordCursor[T]) ([]T, error)

AsList collects all records from the cursor into a slice

func AsListWithContinuation

func AsListWithContinuation[T any](ctx context.Context, cursor RecordCursor[T]) ([]T, []byte, error)

AsListWithContinuation collects all records from the cursor into a slice and returns the final continuation bytes for pagination. Returns nil continuation when the source is exhausted. This is the common pattern for paginated APIs: drain page, return token.

func BuildSPFreshIndex

func BuildSPFreshIndex(ctx context.Context, db *FDBDatabase, storeBuilder func(*FDBRecordContext) (*FDBRecordStore, error), indexName string, seed int64) error

BuildSPFreshIndex bulk-builds an SPFresh index over the store's existing records (RFC-094 §8) and flips it readable. The §8 step order is the foreground-interleaving contract: the COARSE table commits BEFORE the assignment scan, so every record save thereafter can route itself (UpdateWhileWriteOnly stages or goes live by cellfin state), and every record saved before it is covered by the assignment scan's later read versions. Double coverage (a save the scan also reads) is harmless — staging writes are idempotent Sets on the same key.

func CleanupAllHeartbeats

func CleanupAllHeartbeats(tx fdb.WritableTransaction, storeSubspace subspace.Subspace, index *Index)

CleanupAll removes ALL heartbeats for an index. Used during index rebuild or full clear operations.

func DeleteStore

func DeleteStore(ctx *FDBRecordContext, ss subspace.Subspace) error

DeleteStore completely removes all data in a store subspace. Matches Java's FDBRecordStore.deleteStore(context, subspace).

func Filter

func Filter[T any](seq iter.Seq[T], predicate func(T) bool) iter.Seq[T]

Filter returns a filtered sequence

func Filter2

func Filter2[T any](seq iter.Seq2[T, error], predicate func(T) bool) iter.Seq2[T, error]

Filter2 filters a Seq2 sequence

func First

func First[T any](ctx context.Context, cursor RecordCursor[T]) (*T, error)

First returns the first element from a cursor, or nil if empty. Matches Java's RecordCursor.first().

func ForEach

func ForEach[T any](ctx context.Context, cursor RecordCursor[T], fn func(T) error) error

ForEach applies a function to each record in the cursor

func GetCount

func GetCount[T any](ctx context.Context, cursor RecordCursor[T]) (int, error)

GetCount returns the number of elements in a cursor by consuming it. Matches Java's RecordCursor.getCount().

func IsRecordTypeExpression

func IsRecordTypeExpression(expr KeyExpression) bool

IsRecordTypeExpression checks if a key expression starts with record type

func KeyExpressionHasRecordTypePrefix

func KeyExpressionHasRecordTypePrefix(expr KeyExpression) bool

KeyExpressionHasRecordTypePrefix is the exported form of the per-expression prefix check. Used by the SQL layer's covering-index pushdown to decide how to slice a primary-key tuple (first element is the record-type key when true).

func Limit

func Limit[T any](seq iter.Seq[T], n int) iter.Seq[T]

Limit returns at most n values from a sequence

func MBRToTuple

func MBRToTuple(m MBR) tuple.Tuple

MBRToTuple serializes an MBR to a flat tuple [low0, ..., lowN-1, high0, ..., highN-1]. Matches Java's ChildSlot MBR serialization.

func Map

func Map[T, R any](seq iter.Seq[T], fn func(T) R) iter.Seq[R]

Map transforms values in a sequence

func NewHNSWGraph

func NewHNSWGraph(storage *hnswStorage, config HNSWConfig) *hnswGraph

NewHNSWGraph creates a new HNSW graph.

func ReadHeartbeats

func ReadHeartbeats(tx fdb.ReadTransaction, storeSubspace subspace.Subspace, index *Index) ([]*gen.IndexBuildHeartbeat, []string, error)

ReadHeartbeats reads all heartbeats for an index. Useful for diagnostics.

func RebalanceSPFreshIndex

func RebalanceSPFreshIndex(ctx context.Context, db *FDBDatabase, storeBuilder func(*FDBRecordContext) (*FDBRecordStore, error), indexName string) (int, error)

RebalanceSPFreshIndex drains the index's task queue to quiescence: scan, act, repeat until a round acts on nothing (splits enqueue NPA follow-ups, so multiple rounds are normal). Bounded against pathological re-triggering. Returns the total number of lifecycle actions taken.

func Reduce

func Reduce[T any, R any](ctx context.Context, cursor RecordCursor[T], initial R, fn func(R, T) R) (R, error)

Reduce folds all cursor values into a single result using the given function. Matches Java's RecordCursor.reduce().

func RefineSPFreshIndex

func RefineSPFreshIndex(ctx context.Context, db *FDBDatabase, storeBuilder func(*FDBRecordContext) (*FDBRecordStore, error), indexName string, budget int) (int, bool, error)

RefineSPFreshIndex runs ONE budgeted refinement pass over the index (RFC-104): it advances the persistent round-robin cursor by up to `budget` vectors, re-routing each against the current topology and moving the stale ones to recover the closure replication fast ingest never fired. It does NOT drain to quiescence — the deployment runs it on its own cadence (a refinement loop beside the rebalancer loop). Returns (moves, cycleConverged): cycleConverged is true when this call wrapped the cursor AND the whole cycle since the last wrap moved nothing — the signal a caller uses to back off a converged tenant. It is NOT merely "this pass reached the end": a budgeted pass whose tail moves zero does not imply the cycle's earlier passes did.

func RefineSPFreshIndexAll

func RefineSPFreshIndexAll(ctx context.Context, db *FDBDatabase, storeBuilder func(*FDBRecordContext) (*FDBRecordStore, error), indexName string) (int, error)

RefineSPFreshIndexAll is the exported one-shot validation entry (refine every vector once). Production callers use the budgeted RefineSPFreshIndex.

func RegisterFunction

func RegisterFunction(name string, evaluator FunctionEvaluator)

RegisterFunction registers a named function evaluator in the global registry. Call this before building metadata that uses the function.

func RunSPFreshMaintenance

func RunSPFreshMaintenance(ctx context.Context, db *FDBDatabase, opts SPFreshMaintenanceOptions) error

RunSPFreshMaintenance runs the maintenance loop until ctx is canceled, then returns nil. It does an immediate sweep on entry (so a freshly-started worker makes progress without waiting a full interval), then sweeps on SweepInterval and refines on RefineInterval. Per-pass results/errors flow to OnSweep / OnRefine; nothing here fails the loop. With no tenants it is a quiet no-op loop (each pass returns an empty result), so it is safe to start before the tenant list is populated.

func SPFreshAuditTrail

func SPFreshAuditTrail(fineID int64) []string

SPFreshAuditTrail returns the recorded trail for a fineID.

func SPFreshDebugIntegrity

func SPFreshDebugIntegrity(rtx *FDBRecordContext, store *FDBRecordStore, indexName string, sample int) string

SPFreshDebugIntegrity samples up to `sample` pks evenly from the index's OWN membership rows (no assumption about pk shape) and reports, for each, whether every membership target holds the posting entry and what state the target centroid is in. Diagnostics only: it streams the membership keyspace (O(index) reads) — never call it on a production write path.

func SPFreshDebugTopology

func SPFreshDebugTopology(rtx *FDBRecordContext, store *FDBRecordStore, indexName string) string

SPFreshDebugTopology dumps an index's coarse/fine topology summary (benchmark/operational diagnostics).

func SPFreshDisableAudit

func SPFreshDisableAudit()

SPFreshDisableAudit turns the audit log off and releases its memory. Flag first, then the map: a concurrent spfreshAudit that already passed the flag check still finds a (stale, discarded) map under the mutex.

func SPFreshEnableAudit

func SPFreshEnableAudit()

SPFreshEnableAudit turns on the centroid audit log (diagnostics).

func SPFreshHasPendingMaintenance

func SPFreshHasPendingMaintenance(ctx context.Context, db *FDBDatabase, storeBuilder func(*FDBRecordContext) (*FDBRecordStore, error), indexName string) (bool, error)

SPFreshHasPendingMaintenance reports whether the index has any pending maintenance task rows: one snapshot generation read + one limit-1 snapshot range read — the cheap probe that lets a sweeper skip idle tenants without paying a full task scan. Un-bootstrapped indexes have no work by definition.

func Seq2

func Seq2[T any](cursor RecordCursor[T], ctx context.Context) iter.Seq2[T, error]

Seq2 returns an iterator sequence over (value, error) pairs.

func SerializeVector

func SerializeVector(vec []float64) []byte

SerializeVector encodes a float64 vector into the on-disk byte format the HNSW vector index reads (RealVector.fromBytes). Exported so callers/tests can populate a record's vector column.

func ValidateEvolution

func ValidateEvolution(oldMetaData, newMetaData *RecordMetaData) error

ValidateEvolution is a convenience function using the default (strictest) validator.

func ValidateHNSWConfig

func ValidateHNSWConfig(c HNSWConfig) error

ValidateHNSWConfig validates the HNSW configuration. Matches Java's Config validation.

func ValidateRTreeConfig

func ValidateRTreeConfig(config RTreeConfig) error

ValidateRTreeConfig validates the R-tree configuration parameters. Checks: MinM >= 1, MaxM >= 2, SplitS >= 1, NumDimensions >= 1, and S * MaxM >= (S+1) * MinM (split/fuse ratio constraint).

func ValidateSPFreshConfig

func ValidateSPFreshConfig(c SPFreshConfig) error

ValidateSPFreshConfig enforces the invariants the RFC-094 lifecycle and sizing arguments depend on. Called by the maintainer at construction; a violation is a config error, never a silently degraded index.

func ValidateTokenizerVersion

func ValidateTokenizerVersion(t TextTokenizer, version int) error

ValidateTokenizerVersion checks that the given version is within the tokenizer's supported range. Returns an error if out of bounds. Matches Java's TextTokenizer.validateVersion().

func WriteRecordMetaData

func WriteRecordMetaData(meta *RecordMetaData, w io.Writer) error

WriteRecordMetaData serializes a RecordMetaData to the given writer in the canonical `com.apple.foundationdb.record.RecordMetaDataProto.MetaData` wire format — the same bytes FDBMetaDataStore writes into FDB.

Intended for apps with programmatic metadata that want to ship a .pb artifact alongside their binaries so operator tooling (e.g. `frl --meta-file`) can introspect the store without adopting FDBMetaDataStore. Typical use:

func main() {
    meta := buildMyMetaData() // normal RecordMetaDataBuilder
    f, err := os.Create("meta.pb")
    // ... error handling ...
    if err := recordlayer.WriteRecordMetaData(meta, f); err != nil { … }
}

The serialized MetaData includes the embedded `records` FileDescriptorProto and its transitive `dependencies`, so consumers don't need out-of-band access to the app's .proto files to decode records.

Types

type BackendCapabilityError

type BackendCapabilityError struct {
	Op string // the unavailable operation, e.g. "CreateTransaction"
}

BackendCapabilityError is returned when an operation is not supported on the configured fdb backend. The libfdb_c escape hatch (RFC-109) drives the Run / RunRead gold path, standalone transactions (CreateWritableTransaction — used by the FDBDatabaseRunner and SQL BeginTx), and LocalityGetBoundaryKeys (online MUTUAL indexing) all through backend interfaces, so those work on libfdb_c. Only the pure-Go-typed CreateTransaction (which returns the concrete fdb.Transaction) is pure-Go-only in v1; it — and any operation a custom transactor genuinely can't provide — fail fast with this error.

func (*BackendCapabilityError) Error

func (e *BackendCapabilityError) Error() string

type BunchedEntry

type BunchedEntry[K any, V any] struct {
	Key   K
	Value V
}

BunchedEntry is a key-value pair in a BunchedMap.

type BunchedMap

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

BunchedMap is a FoundationDB-backed map that bunches close keys together. Wire-compatible with Java's com.apple.foundationdb.map.BunchedMap.

Currently specialized for TEXT index use (K = tuple.Tuple, V = []int).

When a StoreTimer is set, BunchedMap instruments all writes, deletes, and range reads with index-level counters matching Java's InstrumentedBunchedMap.

func NewBunchedMap

func NewBunchedMap(bunchSize int) *BunchedMap

NewBunchedMap creates a new BunchedMap with the given bunch size.

func NewInstrumentedBunchedMap

func NewInstrumentedBunchedMap(bunchSize int, timer *StoreTimer) *BunchedMap

NewInstrumentedBunchedMap creates a BunchedMap with instrumentation enabled. Matches Java's InstrumentedBunchedMap which wraps BunchedMap with timer hooks.

func (*BunchedMap) Compact

func (m *BunchedMap) Compact(tx fdb.WritableTransaction, ss subspace.Subspace, keyLimit int, continuation []byte) ([]byte, error)

Compact repacks entries in the map to minimize the number of FDB keys used. Each call processes up to keyLimit FDB keys (0 = all keys) and returns a continuation token for multi-transaction compaction. Returns (nil, nil) when compaction is complete. Matches Java's BunchedMap.compact().

func (*BunchedMap) ContainsKey

func (m *BunchedMap) ContainsKey(tx fdb.WritableTransaction, ss subspace.Subspace, key tuple.Tuple) (bool, error)

ContainsKey checks if a key exists in the map. Matches Java's BunchedMap.containsKey().

func (*BunchedMap) Get

Get retrieves the value associated with a key from the map. Returns (value, true, nil) if found, (nil, false, nil) if not found. Always adds a read conflict key on the map key for serializability, matching Java's BunchedMap.get() which takes TransactionContext.

func (*BunchedMap) Put

func (m *BunchedMap) Put(tx fdb.WritableTransaction, ss subspace.Subspace, key tuple.Tuple, value []int) ([]int, bool, error)

Put inserts or updates a key-value pair in the map. Returns (oldValue, true, nil) if the key already existed, (nil, false, nil) if new. Matches Java's BunchedMap.put().

func (*BunchedMap) Remove

func (m *BunchedMap) Remove(tx fdb.WritableTransaction, ss subspace.Subspace, key tuple.Tuple) ([]int, bool, error)

Remove removes a key from the map. Returns (oldValue, true, nil) if found and removed, (nil, false, nil) if not found. Matches Java's BunchedMap.remove().

func (*BunchedMap) Scan

func (m *BunchedMap) Scan(tx fdb.ReadTransaction, ss subspace.Subspace, continuation []byte, limit int, reverse bool) *BunchedMapIterator

Scan iterates over all entries in a single BunchedMap within the given subspace. Supports continuation, limit, and reverse scan. Matches Java's BunchedMap.scan().

func (*BunchedMap) VerifyIntegrity

func (m *BunchedMap) VerifyIntegrity(tx fdb.ReadTransaction, ss subspace.Subspace) error

VerifyIntegrity checks that all signpost keys and entries within bunches are in sorted order. Returns nil if the map is consistent. Matches Java's BunchedMap.verifyIntegrity().

type BunchedMapException

type BunchedMapException struct {
	Message string
}

BunchedMapException is the error type for BunchedMap operations.

func (*BunchedMapException) Error

func (e *BunchedMapException) Error() string

type BunchedMapIterator

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

BunchedMapIterator iterates over a single BunchedMap's entries. Matches Java's BunchedMapIterator.

func (*BunchedMapIterator) Err

func (it *BunchedMapIterator) Err() error

Err returns the first error encountered during iteration, if any.

func (*BunchedMapIterator) GetContinuation

func (it *BunchedMapIterator) GetContinuation() []byte

GetContinuation returns a continuation token for resuming the scan.

func (*BunchedMapIterator) HasNext

func (it *BunchedMapIterator) HasNext() bool

HasNext returns true if there are more entries.

func (*BunchedMapIterator) Next

func (it *BunchedMapIterator) Next() *bunchedEntry

Next returns the next entry.

type BunchedMapMultiIterator

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

BunchedMapMultiIterator iterates over multiple BunchedMaps within a parent subspace. Entries are returned sorted first by subspace, then by key within subspace. Streams from FDB lazily — only one bunch is in memory at a time. Matches Java's BunchedMapMultiIterator.

func NewBunchedMapMultiIterator

func NewBunchedMapMultiIterator(
	tx fdb.ReadTransaction,
	parentSubspace subspace.Subspace,
	splitter SubspaceSplitter,
	beginBytes, endBytes []byte,
	continuation []byte,
	limit int,
	reverse bool,
	serializer *TextIndexBunchedSerializer,
) *BunchedMapMultiIterator

NewBunchedMapMultiIterator creates a multi-map iterator. Streams from FDB lazily — only one bunch in memory at a time.

func NewBunchedMapMultiIteratorWithCallback

func NewBunchedMapMultiIteratorWithCallback(
	tx fdb.ReadTransaction,
	parentSubspace subspace.Subspace,
	splitter SubspaceSplitter,
	beginBytes, endBytes []byte,
	continuation []byte,
	limit int,
	callback KVCallback,
	reverse bool,
	serializer *TextIndexBunchedSerializer,
) *BunchedMapMultiIterator

NewBunchedMapMultiIteratorWithCallback creates a multi-map iterator with a per-KV callback for byte tracking. The callback fires once per raw FDB key-value pair read, before deserialization. Matches Java's scanMulti() with Consumer<KeyValue> callback parameter.

func (*BunchedMapMultiIterator) Cancel

func (it *BunchedMapMultiIterator) Cancel()

Cancel stops the iterator.

func (*BunchedMapMultiIterator) Err

func (it *BunchedMapMultiIterator) Err() error

Err returns the first error encountered during iteration, if any.

func (*BunchedMapMultiIterator) GetContinuation

func (it *BunchedMapMultiIterator) GetContinuation() []byte

GetContinuation returns a continuation token for resuming the scan. Returns nil if the scan is exhausted.

func (*BunchedMapMultiIterator) HasNext

func (it *BunchedMapMultiIterator) HasNext() bool

HasNext returns true if there are more entries to return.

func (*BunchedMapMultiIterator) Next

Next returns the next entry and advances the iterator.

type BunchedMapScanEntry

type BunchedMapScanEntry struct {
	Subspace    subspace.Subspace
	SubspaceTag tuple.Tuple
	Key         tuple.Tuple
	Value       []int
}

BunchedMapScanEntry is a single entry from a multi-map scan. Contains the entry data plus the subspace it belongs to.

type BunchedSerializationError

type BunchedSerializationError struct {
	Message string
	Data    []byte
}

BunchedSerializationError is returned when bunched map serialization/deserialization fails.

func (*BunchedSerializationError) Error

func (e *BunchedSerializationError) Error() string

type BunchedSerializer

type BunchedSerializer[K any, V any] interface {
	SerializeKey(key K) []byte
	SerializeEntry(key K, value V) ([]byte, error)
	SerializeEntries(entries []BunchedEntry[K, V]) ([]byte, error)
	DeserializeKey(data []byte, offset, length int) (K, error)
	DeserializeEntries(key K, data []byte) ([]BunchedEntry[K, V], error)
	DeserializeKeys(key K, data []byte) ([]K, error)
	CanAppend() bool
}

BunchedSerializer serializes keys and values for BunchedMap storage. Keys must serialize in a way that preserves sort order (unsigned lexicographic). Matches Java's com.apple.foundationdb.map.BunchedSerializer interface.

type BytesContinuation

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

BytesContinuation is a simple continuation that wraps a byte array

func NewBytesContinuation

func NewBytesContinuation(b []byte) *BytesContinuation

NewBytesContinuation creates a BytesContinuation with the given bytes. A nil bytes value means end-of-cursor (IsEnd returns true).

func (*BytesContinuation) IsEnd

func (c *BytesContinuation) IsEnd() bool

IsEnd returns true if this is an end continuation

func (*BytesContinuation) ToBytes

func (c *BytesContinuation) ToBytes() ([]byte, error)

ToBytes returns the continuation bytes

type CardinalityFunctionKeyExpression

type CardinalityFunctionKeyExpression struct {
	FunctionKeyExpression
}

CardinalityFunctionKeyExpression is the root key expression of a CARDINALITY() index. It counts the argument array's elements to produce the single key column. Ports Java's CardinalityFunctionKeyExpression:

  • getMinArguments()==getMaxArguments()==1, getColumnSize()==1
  • createsDuplicates()==false (a count is single-valued — see createsDuplicates)
  • evaluateMessage's two protobuf fast paths (plain repeated field, nullable wrapper) plus the materialize-and-count fallback for deeper nestings.

It embeds the generic FunctionKeyExpression so it serialises to the identical proto (Function{name:"cardinality", arguments:…}) and reuses FieldNames / ColumnSize / Name / Arguments. Only Evaluate is overridden to add the fast paths; the result is identical to the registry fallback either way.

func CardinalityExpr

func CardinalityExpr(arguments KeyExpression) *CardinalityFunctionKeyExpression

CardinalityExpr builds a CARDINALITY() index root over the given argument key expression. The argument is field("arr", Concatenate) for a plain array column, or field("arr").nest(field("values", Concatenate)) for a Java-written nullable-array wrapper. Mirrors Java's function("cardinality", field("arr", …)).

func (*CardinalityFunctionKeyExpression) Evaluate

Evaluate applies Java's two protobuf fast paths against the record message, falling back to materialize-and-count for shapes the fast paths do not recognise (deeper nesting, the null cases).

Fast path 1 — nullable-array wrapper: the argument is field("wrapper").nest(field("values", Concatenate)). If the wrapper message is present, count its "values" field directly (a present wrapper with zero elements is a non-null empty array → 0). If absent, the array is NULL → fall through to the materialized null result.

Fast path 2 — plain repeated field: the argument is field("arr", Concatenate). Count the repeated field directly (Message.getRepeatedFieldCount). A zero count maps to a NULL key, because on Go-written records an empty array is wire-indistinguishable from NULL/unset — consistent with the scalar CardinalityValue (RFC-143 §3a).

type ChildSlot

type ChildSlot struct {
	SmallestHV  *big.Int
	SmallestKey tuple.Tuple
	LargestHV   *big.Int
	LargestKey  tuple.Tuple
	ChildID     []byte
	ChildMBR    MBR
}

ChildSlot is an intermediate node slot referencing a child node.

func (ChildSlot) GetMBR

func (s ChildSlot) GetMBR() MBR

GetMBR returns the MBR of the child subtree.

type CommitCheckFunc

type CommitCheckFunc func() error

CommitCheckFunc is a pre-commit check that runs before the transaction commits. If it returns an error, the commit is aborted. Matches Java's CommitCheckAsync interface.

type ComparisonKeyFunc

type ComparisonKeyFunc[T any] func(T) tuple.Tuple

ComparisonKeyFunc extracts a comparison key from a cursor element. The returned tuple is used for merge ordering via FDB's order-preserving tuple encoding. Matches Java's KeyedMergeCursorState.comparisonKeyFunction.

type CompositeKeyExpression

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

CompositeKeyExpression combines multiple key expressions

func (*CompositeKeyExpression) ColumnSize

func (c *CompositeKeyExpression) ColumnSize() int

ColumnSize returns the sum of all child column sizes.

func (*CompositeKeyExpression) Evaluate

func (c *CompositeKeyExpression) Evaluate(record *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

Evaluate computes the Cartesian product of all child expression results. Matches Java's ThenKeyExpression which crosses children:

child0 returns [[1], [2]]
child1 returns [[a], [b]]
result = [[1,a], [1,b], [2,a], [2,b]]

For the common case where each child returns exactly one tuple, the result is a single tuple that is the concatenation of all child tuples — identical to the old flat-append behavior.

func (*CompositeKeyExpression) EvaluateFlat

func (c *CompositeKeyExpression) EvaluateFlat(record *FDBStoredRecord[proto.Message], msg proto.Message) ([]any, error)

EvaluateFlat returns the single concatenated tuple directly, avoiding the outer [][]any wrapper. Only valid when no child uses fan-out. Saves 1 alloc per child (no [][]any) + 1 alloc for the result (no outer wrapper).

func (*CompositeKeyExpression) FieldNames

func (c *CompositeKeyExpression) FieldNames() []string

FieldNames returns all field names from component expressions

func (*CompositeKeyExpression) PackDirect

func (c *CompositeKeyExpression) PackDirect(pk *tuple.Packer, record *FDBStoredRecord[proto.Message], msg proto.Message) bool

PackDirect encodes all child fields directly into a Packer. Returns false if any child can't be directly packed.

func (*CompositeKeyExpression) SubKeyExpressions

func (c *CompositeKeyExpression) SubKeyExpressions() []KeyExpression

SubKeyExpressions returns the child key expressions in key order. Mirrors Java's ThenKeyExpression.getChildren(); used by callers that need to inspect the composite's structure (e.g. tagging which columns are function-keyed). The returned slice is the live backing slice — callers must not mutate it.

func (*CompositeKeyExpression) ToKeyExpression

func (c *CompositeKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes a CompositeKeyExpression (ThenKeyExpression) to proto. Matches Java's ThenKeyExpression.toKeyExpression().

type ContinuationParseError

type ContinuationParseError struct {
	Message  string
	RawBytes []byte
	Cause    error
}

ContinuationParseError is returned when continuation bytes fail to parse as their wrapper proto. Matches Java's RecordCoreException("error parsing continuation") with the "raw_bytes" log info key (e.g. OrElseCursor's constructor, RecordCursor.fromList): a corrupt continuation is a caller error and must surface, never be silently treated as a fresh start.

Message overrides the default "error parsing continuation" text for the Java classes whose RecordCoreException wording differs (ConcatCursor uses "Error parsing ConcatCursor continuation", DedupCursor uses "Error parsing continuation"). Leave empty for the common wording.

func (*ContinuationParseError) Error

func (e *ContinuationParseError) Error() string

func (*ContinuationParseError) Unwrap

func (e *ContinuationParseError) Unwrap() error

type Counter

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

Counter tracks count and cumulative value (nanoseconds for timed events, bytes for size events). All operations are goroutine-safe.

func (*Counter) Count

func (c *Counter) Count() int64

Count returns the number of observations recorded.

func (*Counter) CumulativeValue

func (c *Counter) CumulativeValue() int64

CumulativeValue returns the sum of all recorded values.

func (*Counter) Increment

func (c *Counter) Increment(amount int64)

Increment adds amount to both count and cumulative value.

func (*Counter) Record

func (c *Counter) Record(value int64)

Record records a single observation with the given value. For timed events, value is nanoseconds. For size events, value is bytes.

func (*Counter) Reset

func (c *Counter) Reset()

Reset zeroes the counter.

type CounterSnapshot

type CounterSnapshot struct {
	Count           int64
	CumulativeValue int64
}

CounterSnapshot is an immutable point-in-time snapshot of a Counter.

type CursorFactory

type CursorFactory[T any] func(continuation []byte) RecordCursor[T]

CursorFactory creates a cursor from an optional continuation. nil continuation means start from the beginning.

type CursorStreamingMode

type CursorStreamingMode int

CursorStreamingMode controls how FDB fetches data

const (
	// StreamingModeSmall fetches small amounts at a time
	StreamingModeSmall CursorStreamingMode = iota
	// StreamingModeMedium fetches medium amounts at a time
	StreamingModeMedium
	// StreamingModeLarge fetches large amounts at a time
	StreamingModeLarge
	// StreamingModeSerial fetches one at a time
	StreamingModeSerial
	// StreamingModeWantAll fetches as much as possible
	StreamingModeWantAll
	// StreamingModeIterator is the default iterator mode
	StreamingModeIterator
)

func (CursorStreamingMode) ToFDB

ToFDB converts to FDB's StreamingMode

type DefaultTextTokenizer

type DefaultTextTokenizer struct{}

DefaultTextTokenizer is the default tokenizer for full-text indexes. It splits text using Unicode word boundary rules, normalizes to NFKD, case-folds to lowercase, and strips diacritical marks. Matches Java's com.apple.foundationdb.record.provider.common.text.DefaultTextTokenizer.

func DefaultTextTokenizerInstance

func DefaultTextTokenizerInstance() *DefaultTextTokenizer

DefaultTextTokenizerInstance returns the singleton default tokenizer.

func (*DefaultTextTokenizer) MaxVersion

func (t *DefaultTextTokenizer) MaxVersion() int

MaxVersion returns the same as MinVersion (only one version exists).

func (*DefaultTextTokenizer) MinVersion

func (t *DefaultTextTokenizer) MinVersion() int

MinVersion returns 0 (GLOBAL_MIN_VERSION).

func (*DefaultTextTokenizer) Name

func (t *DefaultTextTokenizer) Name() string

Name returns "default".

func (*DefaultTextTokenizer) Tokenize

func (t *DefaultTextTokenizer) Tokenize(text string, version int, mode TokenizerMode) (TokenIterator, error)

Tokenize returns an iterator over tokens from the input text. Returns an error if the version is out of bounds. The tokenization process:

  1. Segment text into words using Unicode word boundary rules (matching Java's BreakIterator.getWordInstance(Locale.ROOT))
  2. NFKD normalize each segment
  3. Filter segments that don't contain any letter or digit
  4. Lowercase and strip combining marks (\p{M})

func (*DefaultTextTokenizer) TokenizeToList

func (t *DefaultTextTokenizer) TokenizeToList(text string, version int, mode TokenizerMode) ([]string, error)

TokenizeToList returns all tokens as a list.

func (*DefaultTextTokenizer) TokenizeToMap

func (t *DefaultTextTokenizer) TokenizeToMap(text string, version int, mode TokenizerMode) (map[string][]int, error)

TokenizeToMap returns a map from token to list of positions.

type DefaultTextTokenizerFactory

type DefaultTextTokenizerFactory struct{}

DefaultTextTokenizerFactory creates DefaultTextTokenizer instances.

func (*DefaultTextTokenizerFactory) GetTokenizer

func (f *DefaultTextTokenizerFactory) GetTokenizer() TextTokenizer

func (*DefaultTextTokenizerFactory) Name

type DimensionsKeyExpression

type DimensionsKeyExpression struct {
	WholeKey       KeyExpression
	PrefixSize     int
	DimensionsSize int
}

DimensionsKeyExpression splits a key expression into prefix, dimensions, and suffix. Used by MULTIDIMENSIONAL indexes to separate grouping, spatial, and key-suffix components. Matches Java's DimensionsKeyExpression.

func Dimensions

func Dimensions(wholeKey KeyExpression, prefixSize, dimensionsSize int) *DimensionsKeyExpression

Dimensions creates a DimensionsKeyExpression.

func (*DimensionsKeyExpression) ColumnSize

func (d *DimensionsKeyExpression) ColumnSize() int

ColumnSize returns the column size of the whole key.

func (*DimensionsKeyExpression) Evaluate

func (d *DimensionsKeyExpression) Evaluate(record *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

Evaluate delegates to the whole key expression.

func (*DimensionsKeyExpression) FieldNames

func (d *DimensionsKeyExpression) FieldNames() []string

FieldNames delegates to the whole key.

func (*DimensionsKeyExpression) SplitIndexEntry

func (d *DimensionsKeyExpression) SplitIndexEntry(entry tuple.Tuple) (prefix, dims, suffix tuple.Tuple)

SplitIndexEntry splits an evaluated index entry tuple into prefix, dimensions, and suffix.

func (*DimensionsKeyExpression) SuffixSize

func (d *DimensionsKeyExpression) SuffixSize() int

SuffixSize returns the number of suffix columns (after prefix + dimensions).

func (*DimensionsKeyExpression) ToKeyExpression

func (d *DimensionsKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes to proto.

type DirectPacker

type DirectPacker interface {
	PackDirect(pk *tuple.Packer, record *FDBStoredRecord[proto.Message], msg proto.Message) bool
}

DirectPacker can encode field values directly into a Packer without any boxing.

type EmptyKeyExpression

type EmptyKeyExpression struct{}

EmptyKeyExpression produces an empty tuple — used for ungrouped record counting. When used as a recordCountKey, a single total count is maintained.

func (*EmptyKeyExpression) ColumnSize

func (e *EmptyKeyExpression) ColumnSize() int

ColumnSize returns 0 — an empty expression produces no tuple elements.

func (*EmptyKeyExpression) Evaluate

Evaluate returns one empty tuple (no key components).

func (*EmptyKeyExpression) EvaluateFlat

func (e *EmptyKeyExpression) EvaluateFlat(_ *FDBStoredRecord[proto.Message], _ proto.Message) ([]any, error)

EvaluateFlat returns empty (no elements to append).

func (*EmptyKeyExpression) FieldNames

func (e *EmptyKeyExpression) FieldNames() []string

FieldNames returns no field names.

func (*EmptyKeyExpression) ToKeyExpression

func (e *EmptyKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes an EmptyKeyExpression to proto. Matches Java's EmptyKeyExpression.toKeyExpression().

type EndContinuation

type EndContinuation struct{}

EndContinuation represents the end of a cursor's iteration. INVARIANT: Only valid when NoNextReason is SourceExhausted. Matches Java's RecordCursorEndContinuation.

func (*EndContinuation) IsEnd

func (c *EndContinuation) IsEnd() bool

IsEnd always returns true for end continuations

func (*EndContinuation) ToBytes

func (c *EndContinuation) ToBytes() ([]byte, error)

ToBytes always returns nil for end continuations

type EndpointType

type EndpointType int

EndpointType represents how to treat range endpoints in scans

const (
	// EndpointTypeTreeStart indicates the start of the entire tree
	EndpointTypeTreeStart EndpointType = iota
	// EndpointTypeTreeEnd indicates the end of the entire tree
	EndpointTypeTreeEnd
	// EndpointTypeRangeInclusive includes the endpoint in the range
	EndpointTypeRangeInclusive
	// EndpointTypeRangeExclusive excludes the endpoint from the range
	EndpointTypeRangeExclusive
	// EndpointTypeContinuation indicates continuation from a previous scan
	EndpointTypeContinuation
	// EndpointTypePrefixString for prefix-string-based ranges.
	// When used, the tuple is packed and the trailing null byte (string
	// terminator in FDB tuple encoding) is stripped.  For the low
	// endpoint the stripped bytes are used directly.  For the high
	// endpoint the stripped bytes are strinc'd (trailing 0xFF bytes are
	// removed, then the last byte is incremented).
	// Matches Java's EndpointType.PREFIX_STRING.
	EndpointTypePrefixString
)

type Event

type Event struct {
	Name  string // machine-readable, e.g. "save_record"
	Title string // human-readable, e.g. "Save Record"
}

Event represents a measurable instrumentation event. Matches Java's FDBStoreTimer.Events / FDBStoreTimer.Counts.

type ExecuteProperties

type ExecuteProperties struct {
	// IsolationLevel for the execution
	IsolationLevel IsolationLevel

	// ReturnedRowLimit is the maximum number of records to return
	// 0 or negative means no limit
	ReturnedRowLimit int

	// ScannedRecordsLimit is the maximum number of records to scan
	// 0 or negative means no limit
	ScannedRecordsLimit int

	// ScannedBytesLimit is the maximum number of bytes to scan
	// 0 or negative means no limit
	ScannedBytesLimit int64

	// TimeLimit is the maximum time for the operation
	// Zero duration means no limit
	TimeLimit time.Duration

	// DefaultCursorStreamingMode is the default streaming mode for cursors
	DefaultCursorStreamingMode CursorStreamingMode

	// FailOnScanLimitReached determines if hitting scan limits should fail the operation
	FailOnScanLimitReached bool

	// Skip is the number of records to skip before returning results.
	// Matches Java's ExecuteProperties.getSkip().
	Skip int

	// MaterializationLimit caps the number of rows that may be buffered
	// in memory by operators that materialize an entire relation (NLJ
	// inner, UNION buffered, recursive CTE levels). Zero means use
	// DefaultMaterializationLimit.
	MaterializationLimit int

	// State is the statement-scoped mutable counter object (RFC-130),
	// mirroring Java's ExecuteState held by reference inside the otherwise
	// value-copied ExecuteProperties. It is a POINTER, so every value-copy of
	// ExecuteProperties (the WithX helpers, ClearSkipAndLimit, per-operator
	// innerProps) shares ONE counter and none of them reset it — the
	// statement-wide memory byte budget survives all inner-plan resets
	// structurally, which is the whole point. It is always minted once per
	// statement (never nil) where the statement's ExecuteProperties is first
	// built; the "no budget" case is memLimit<=0, NOT a nil State, so a missed
	// accumulation site charges an unlimited counter rather than silently
	// no-oping. None of the WithX helpers below clear it: they copy the value
	// struct, which copies the pointer.
	State *ExecuteState

	// DryRun, when true, makes data-modification execution validate and PREVIEW
	// each mutation via the store's DryRun* primitives instead of staging a real
	// write — Java's ExecuteProperties.setDryRun / isDryRun(). Statement-scoped:
	// it is sourced from the SQL OPTIONS (DRY RUN) clause carried on
	// paginatingRows, never from a connection option (a connection-scoped flag
	// would go sticky across pooled statements).
	DryRun bool
}

ExecuteProperties holds properties that pertain to an entire execution

func DefaultExecuteProperties

func DefaultExecuteProperties() ExecuteProperties

DefaultExecuteProperties returns properties with sensible defaults

func (ExecuteProperties) ClearRowAndTimeLimits

func (e ExecuteProperties) ClearRowAndTimeLimits() ExecuteProperties

ClearRowAndTimeLimits returns a copy with row limit and time limit cleared. Matches Java's ExecuteProperties.clearRowAndTimeLimits().

func (ExecuteProperties) ClearSkipAndLimit

func (e ExecuteProperties) ClearSkipAndLimit() ExecuteProperties

ClearSkipAndLimit returns a copy with skip and row limit cleared. Matches Java's ExecuteProperties.clearSkipAndLimit().

func (ExecuteProperties) GetMaterializationLimit

func (e ExecuteProperties) GetMaterializationLimit() int

GetMaterializationLimit returns the effective materialization limit, falling back to DefaultMaterializationLimit when zero.

func (ExecuteProperties) WithDryRun

func (e ExecuteProperties) WithDryRun(dryRun bool) ExecuteProperties

WithDryRun returns a copy with the dry-run flag set. Java's ExecuteProperties.setDryRun.

func (ExecuteProperties) WithIsolationLevel

func (e ExecuteProperties) WithIsolationLevel(level IsolationLevel) ExecuteProperties

WithIsolationLevel returns a copy with the specified isolation level

func (ExecuteProperties) WithMaterializationLimit

func (e ExecuteProperties) WithMaterializationLimit(limit int) ExecuteProperties

WithMaterializationLimit returns a copy with the specified materialization limit.

func (ExecuteProperties) WithReturnedRowLimit

func (e ExecuteProperties) WithReturnedRowLimit(limit int) ExecuteProperties

WithReturnedRowLimit returns a copy with the specified row limit

func (ExecuteProperties) WithScannedBytesLimit

func (e ExecuteProperties) WithScannedBytesLimit(limit int64) ExecuteProperties

WithScannedBytesLimit returns a copy with the specified scanned bytes limit.

func (ExecuteProperties) WithScannedRecordsLimit

func (e ExecuteProperties) WithScannedRecordsLimit(limit int) ExecuteProperties

WithScannedRecordsLimit returns a copy with the specified scanned records limit.

func (ExecuteProperties) WithSkip

func (e ExecuteProperties) WithSkip(skip int) ExecuteProperties

WithSkip returns a copy with the specified skip count.

func (ExecuteProperties) WithTimeLimit

func (e ExecuteProperties) WithTimeLimit(limit time.Duration) ExecuteProperties

WithTimeLimit returns a copy with the specified time limit

type ExecuteState

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

ExecuteState holds the mutable, statement-scoped counters for a single statement execution. It mirrors Java's com.apple.foundationdb.record.ExecuteState (ExecuteState.java:44-47): the counters live in a small mutable object held BY REFERENCE inside the otherwise value-copied ExecuteProperties, so every value-copy of the properties (the WithX helpers, ClearSkipAndLimit, per-operator innerProps) shares one counter and none of them reset it. Statement-wide survival is therefore STRUCTURAL — exactly as in Java, where clearSkipAndLimit (:240-245) preserves the ExecuteState for free because it only zeroes skip/rowLimit.

RFC-130: the only counter tracked here today is the statement-wide memory byte budget that bounds in-memory buffering operators (the row-count MaterializationLimit cannot stop 100k LARGE rows from OOMing). The scan/byte/time counters Go currently tracks per-cursor are the correct future home here too, to fully match Java — out of scope for RFC-130, noted for the divergence ledger.

Concurrency: the executor is single-threaded per statement (zero goroutine launches in pkg/recordlayer/query/executor — pinned by package_invariant_test.go), so ChargeMemory needs no mutex/atomic. If a future parallel-union breaks that invariant the pinned test fires and the counter moves to atomic.

func NewExecuteState

func NewExecuteState(memLimit int64) *ExecuteState

NewExecuteState mints a fresh statement-scoped state with the given memory byte limit. A limit <= 0 means unlimited (no budget). The state is ALWAYS minted once per statement — never nil — so a missed accumulation site charges an unlimited counter (a no-op charge) rather than silently no-oping via a nil receiver, which would make a missed wiring an invisible bypass instead of a visible (if unbounded) charge.

func (*ExecuteState) ChargeMemory

func (s *ExecuteState) ChargeMemory(n int64) error

ChargeMemory adds n bytes to the statement's running memory total and returns a *MemoryLimitExceededError if the total then exceeds the budget.

A nil receiver or a non-positive memLimit means "no budget" and is a no-op (memUsed is still accumulated for an active budget, but a <=0 limit short- circuits before touching the counter so the unlimited path stays free). The charge is applied BEFORE the check, so the error carries the would-be total — the buffer that breaches the budget is never kept by the caller, which errors out instead of appending.

func (*ExecuteState) HasMemLimit

func (s *ExecuteState) HasMemLimit() bool

HasMemLimit reports whether a positive memory budget is active. Callers MUST gate any expensive byte-estimate computation (e.g. the per-row proto Size() walk in estimateQueryResultBytes) on this, so the default/unlimited path pays nothing — RFC-130's zero-overhead-when-off invariant. nil receiver or memLimit<=0 → false.

func (*ExecuteState) MemLimit

func (s *ExecuteState) MemLimit() int64

MemLimit returns the configured memory byte budget (<= 0 == unlimited).

func (*ExecuteState) MemUsed

func (s *ExecuteState) MemUsed() int64

MemUsed returns the bytes charged against this state so far. Test/diagnostic accessor; production code never reads it.

type FDBDatabase

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

FDBDatabase provides access to the underlying FoundationDB database or tenant and manages transaction execution with retry logic. This is the Record Layer equivalent of Java's FDBDatabase.

The transactor field can be either an fdb.Database or fdb.Tenant, both of which implement the fdb.Transactor interface. This allows transparent support for both regular database operations and tenant-isolated operations.

func NewFDBDatabase

func NewFDBDatabase(db fdb.Database) *FDBDatabase

NewFDBDatabase creates a new FDBDatabase wrapping the core FDB database

func NewFDBDatabaseFromTenant

func NewFDBDatabaseFromTenant(tenant fdb.Tenant) *FDBDatabase

NewFDBDatabaseFromTenant creates a new FDBDatabase wrapping an FDB tenant for tenant-isolated operations. All operations will be scoped to the tenant's keyspace.

func NewFDBDatabaseWithBackend

func NewFDBDatabaseWithBackend(backend fdb.BackendDatabase) *FDBDatabase

NewFDBDatabaseWithBackend creates an FDBDatabase driven by a build-selected fdb backend (RFC-109) — e.g. the libfdb_c escape hatch, opened via fdbclient.Open (which a build tag points at the pure-Go or libfdb_c client). The backend drives the Run / RunRead gold path (record save/load, query, index maintenance) through the Transactor interface.

The concrete-db slot is left empty for a non-pure-Go backend. Standalone transactions go through CreateWritableTransaction and locality through LocalityGetBoundaryKeys — both delegate to the backend's own interface-returning methods, so explicit transactions, the FDBDatabaseRunner, AND online MUTUAL indexing all work on libfdb_c. The one remaining concrete-only path is the pure-Go-typed CreateTransaction (it returns the concrete fdb.Transaction a non-pure-Go backend cannot build), which stays pure-Go-only in v1 and fails fast with BackendCapabilityError (not a nil panic) — the same scope boundary the RFC draws around tenants.

func NewFDBDatabaseWithTransactor

func NewFDBDatabaseWithTransactor(transactor fdb.Transactor, db fdb.Database) *FDBDatabase

NewFDBDatabaseWithTransactor creates a new FDBDatabase with a custom Transactor. The transactor is used for Run()/RunWithVersionstamp() (transaction execution), while the db is used for CreateTransaction() (direct transaction creation). This enables wrapping the transactor for fault injection, tracing, or middleware.

func (*FDBDatabase) CreateTransaction

func (d *FDBDatabase) CreateTransaction() (fdb.Transaction, error)

CreateTransaction creates a new transaction without retry logic. This is primarily used for testing scenarios where manual transaction control is needed, such as testing isolation levels with concurrent transactions. For tenant-isolated databases, the transaction will be scoped to the tenant's keyspace.

func (*FDBDatabase) CreateWritableTransaction

func (d *FDBDatabase) CreateWritableTransaction() (fdb.WritableTransaction, error)

CreateWritableTransaction creates a standalone, non-retry transaction as the backend-agnostic WritableTransaction interface. Unlike CreateTransaction (which returns the concrete pure-Go fdb.Transaction and is therefore pure-Go-only), this works on ANY backend — including the libfdb_c escape hatch — so the SQL engine's database/sql explicit transactions (BeginTx / COMMIT, which span multiple driver calls and so can't use the closure-based Run gold path) are not silently pure-Go-only. Prefer this over CreateTransaction wherever a concrete pure-Go handle isn't specifically required.

func (*FDBDatabase) GetStoreStateCache

func (d *FDBDatabase) GetStoreStateCache() FDBRecordStoreStateCache

GetStoreStateCache returns the current store state cache. Matches Java's FDBDatabase.getStoreStateCache().

func (*FDBDatabase) LocalityGetBoundaryKeys

func (d *FDBDatabase) LocalityGetBoundaryKeys(r fdb.ExactRange, limit int, readVersion int64) ([]fdb.Key, error)

LocalityGetBoundaryKeys returns the FDB shard boundary keys within r, working on both the pure-Go and libfdb_c backends (the online MUTUAL indexer uses them to partition the keyspace into fragments for concurrent building). It's a read of the \xff/keyServers system range — byte-identical on the pure-Go and libfdb_c clients against the same cluster — so mutual indexing parallelizes on either backend. A handle that can't provide it (a tenant-backed FDBDatabase, or a custom transactor) returns BackendCapabilityError; callers that want graceful degradation (1 fragment) treat an error as "no boundaries".

Unlike CreateWritableTransaction there is no tenant branch: shard boundaries are a cluster-wide property of the keyServers map, independent of any tenant.

func (*FDBDatabase) Run

func (d *FDBDatabase) Run(ctx context.Context, fn func(rtx *FDBRecordContext) (any, error)) (any, error)

Run executes a function within a transaction with automatic retry handling. Before committing, flushes any queued versionstamp mutations. Matches Java's FDBRecordContext.commitAsync() behavior.

func (*FDBDatabase) RunRead

func (d *FDBDatabase) RunRead(ctx context.Context, fn func(rtx fdb.ReadTransaction) (any, error)) (any, error)

RunRead executes a read-only function with automatic retry but no commit. Uses ReadTransact under the hood — no write conflict ranges, no commit round-trip. Suitable for statistics, metadata reads, or any read-only operation where a full read-write transaction would waste a commit.

ctx bounds the read-retry loop + backoff when the transactor supports it (fdb.CtxReadTransactor); the entry check also returns early if already cancelled.

func (*FDBDatabase) RunWithVersionstamp

func (d *FDBDatabase) RunWithVersionstamp(ctx context.Context, fn func(rtx *FDBRecordContext) (any, error)) (any, []byte, error)

RunWithVersionstamp is like Run but also returns the committed versionstamp. Use this when you need the versionstamp after commit (e.g. for record versioning). Returns (result, versionstamp, error). Versionstamp is nil for read-only transactions.

func (*FDBDatabase) RunWithWeakReads

func (d *FDBDatabase) RunWithWeakReads(ctx context.Context, weak WeakReadSemantics, fn func(rtx *FDBRecordContext) (any, error)) (any, error)

RunWithWeakReads is like Run but applies weak read semantics to the transaction. If IsCausalReadRisky is set, the transaction reads from any replica. Matches Java's FDBDatabase.openContext(config, timer, weakReadSemantics, ...).

func (*FDBDatabase) SetStoreStateCache

func (d *FDBDatabase) SetStoreStateCache(cache FDBRecordStoreStateCache)

SetStoreStateCache sets the cache used for store state across transactions. Matches Java's FDBDatabase.setStoreStateCache().

type FDBDatabaseFactory

type FDBDatabaseFactory struct {

	// StoreStateCacheFactory creates a store state cache for each new database.
	// If nil, PassThroughStoreStateCache is used.
	StoreStateCacheFactory func() FDBRecordStoreStateCache
	// contains filtered or unexported fields
}

FDBDatabaseFactory caches FDBDatabase instances by cluster file path. Thread-safe. Matches Java's FDBDatabaseFactory.getDatabase(clusterFile).

func NewFDBDatabaseFactory

func NewFDBDatabaseFactory() *FDBDatabaseFactory

NewFDBDatabaseFactory creates a factory for caching database instances.

func (*FDBDatabaseFactory) GetDatabase

func (f *FDBDatabaseFactory) GetDatabase(clusterFile string) (*FDBDatabase, error)

GetDatabase returns a cached FDBDatabase for the given cluster file path. Creates a new one on first call for each unique path. Matches Java's FDBDatabaseFactory.getDatabase(clusterFile).

type FDBDatabaseRunner

type FDBDatabaseRunner struct {

	// MaxAttempts is the maximum number of retry attempts (default 10).
	MaxAttempts int

	// InitialDelay is the initial delay between retries (default 10ms).
	InitialDelay time.Duration

	// MaxDelay is the maximum delay between retries (default 1s).
	MaxDelay time.Duration

	// ContextConfig is applied to each transaction.
	ContextConfig *RecordContextConfig
	// contains filtered or unexported fields
}

FDBDatabaseRunner provides configurable retry logic for FDB transactions. Matches Java's FDBDatabaseRunnerImpl.

func NewFDBDatabaseRunner

func NewFDBDatabaseRunner(db *FDBDatabase) *FDBDatabaseRunner

NewFDBDatabaseRunner creates a runner with default settings.

func (*FDBDatabaseRunner) OpenContext

func (r *FDBDatabaseRunner) OpenContext(ctx context.Context) (*FDBRecordContext, error)

OpenContext creates a new FDBRecordContext with a fresh transaction, applying the runner's context configuration. Matches Java's FDBDatabaseRunner.openContext(). The caller is responsible for committing or cancelling the transaction.

func (*FDBDatabaseRunner) RunWithRetry

func (r *FDBDatabaseRunner) RunWithRetry(ctx context.Context, fn func(rtx *FDBRecordContext) (any, error)) (any, error)

RunWithRetry executes fn with configurable retry logic and exponential backoff. Retries on FDB retryable errors (conflict, etc.) up to MaxAttempts times. Non-retryable errors are returned immediately. Matches Java's FDBDatabaseRunnerImpl.run().

func (*FDBDatabaseRunner) SetContextConfig

func (r *FDBDatabaseRunner) SetContextConfig(config *RecordContextConfig) *FDBDatabaseRunner

SetContextConfig sets the transaction context configuration.

func (*FDBDatabaseRunner) SetInitialDelay

func (r *FDBDatabaseRunner) SetInitialDelay(d time.Duration) *FDBDatabaseRunner

SetInitialDelay sets the initial retry delay.

func (*FDBDatabaseRunner) SetMaxAttempts

func (r *FDBDatabaseRunner) SetMaxAttempts(n int) *FDBDatabaseRunner

SetMaxAttempts sets the maximum retry attempts.

func (*FDBDatabaseRunner) SetMaxDelay

func (r *FDBDatabaseRunner) SetMaxDelay(d time.Duration) *FDBDatabaseRunner

SetMaxDelay sets the maximum retry delay.

type FDBIndexedRecord

type FDBIndexedRecord struct {
	IndexEntry *IndexEntry
	Record     *FDBStoredRecord[proto.Message]
}

FDBIndexedRecord wraps a record that was found via an index scan. Contains both the index entry used to locate the record and the record itself. Matches Java's com.apple.foundationdb.record.provider.foundationdb.FDBIndexedRecord.

type FDBMetaDataStore

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

FDBMetaDataStore stores and retrieves RecordMetaData from FDB. The metadata is stored as a serialized protobuf at a well-known key, enabling runtime schema evolution without application redeployment. Matches Java's FDBMetaDataStore.

func NewFDBMetaDataStore

func NewFDBMetaDataStore(ss subspace.Subspace) *FDBMetaDataStore

NewFDBMetaDataStore creates a metadata store at the given subspace. The evolution validator defaults to the strictest configuration, matching Java's `evolutionValidator = MetaDataEvolutionValidator.getDefaultInstance()`.

func (*FDBMetaDataStore) LoadRecordMetaDataProto

func (s *FDBMetaDataStore) LoadRecordMetaDataProto(tx fdb.WritableTransaction) (*gen.MetaData, error)

LoadRecordMetaDataProto loads the current MetaData proto from FDB. Returns nil if no metadata has been stored. Uses SplitHelper for wire compatibility with Java's FDBMetaDataStore. Matches Java's FDBMetaDataStore.loadRecordMetaData().

func (*FDBMetaDataStore) LoadRecordMetaDataProtoAtVersion

func (s *FDBMetaDataStore) LoadRecordMetaDataProtoAtVersion(tx fdb.WritableTransaction, version int32) (*gen.MetaData, error)

LoadRecordMetaDataProtoAtVersion loads a historical version of the metadata. Returns nil if the version doesn't exist. Uses SplitHelper for wire compatibility with Java's FDBMetaDataStore.

func (*FDBMetaDataStore) SaveRecordMetaData

func (s *FDBMetaDataStore) SaveRecordMetaData(tx fdb.WritableTransaction, metaDataProto *gen.MetaData) error

SaveRecordMetaData saves a MetaData proto to FDB, with the full validation Java runs in the same transaction — this is NOT a raw persist. In order (matching Java's FDBMetaDataStore.saveAndSetCurrent):

  1. the new proto must build into a RecordMetaData;
  2. if metadata is already stored: the new version must be strictly greater (MetaDataVersionMustIncreaseError otherwise), the evolution validator must pass old → new, and the old serialized bytes are archived at HISTORY_KEY_PREFIX + oldVersion;
  3. the new metadata is written at CURRENT_KEY.

Because all of this happens inside the caller's transaction, FDB conflict detection serializes concurrent evolvers — two racing saves against the same old version cannot both commit.

Uses SplitHelper for wire compatibility with Java's FDBMetaDataStore, which stores metadata with split support (unsplit suffix 0).

func (*FDBMetaDataStore) SetEvolutionValidator

func (s *FDBMetaDataStore) SetEvolutionValidator(v *MetaDataEvolutionValidator)

SetEvolutionValidator replaces the validator SaveRecordMetaData runs against the currently stored metadata. Matches Java's FDBMetaDataStore.setEvolutionValidator().

func (*FDBMetaDataStore) Subspace

func (s *FDBMetaDataStore) Subspace() subspace.Subspace

Subspace returns the subspace this metadata store uses.

type FDBRecordContext

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

func NewFDBRecordContext

func NewFDBRecordContext(tx fdb.WritableTransaction) *FDBRecordContext

NewFDBRecordContext creates a new FDBRecordContext wrapping an FDB transaction. This is primarily used for testing scenarios where direct transaction control is needed.

func (*FDBRecordContext) AddCommitCheck

func (rc *FDBRecordContext) AddCommitCheck(check CommitCheckFunc)

AddCommitCheck registers a pre-commit check function. All checks run before the transaction commits. If any returns an error, the commit is aborted with that error. Goroutine-safe via commitMu (matches Java's synchronized blocks). Matches Java's FDBRecordContext.addCommitCheck(CommitCheckAsync).

func (*FDBRecordContext) AddPostCommit

func (rc *FDBRecordContext) AddPostCommit(hook PostCommitFunc)

AddPostCommit registers a post-commit callback. All callbacks run after the transaction successfully commits. Goroutine-safe via commitMu (matches Java's synchronized blocks). Matches Java's FDBRecordContext.addPostCommit(PostCommit).

func (*FDBRecordContext) AddReadConflictRange

func (rc *FDBRecordContext) AddReadConflictRange(r fdb.ExactRange) error

AddReadConflictRange adds a read conflict range and tracks it for diagnostics. Goroutine-safe via conflictMu (FDB transaction is already goroutine-safe).

func (*FDBRecordContext) AddToLocalVersionCache

func (rc *FDBRecordContext) AddToLocalVersionCache(versionKey []byte, localVersion int)

AddToLocalVersionCache caches a local version for a version key within this transaction. Goroutine-safe via versionMu. Matches Java's FDBRecordContext.addToLocalVersionCache().

func (*FDBRecordContext) AddVersionMutation

func (rc *FDBRecordContext) AddVersionMutation(mutationType VersionMutationType, versionKey []byte, value []byte)

AddVersionMutation queues a versionstamp mutation to be applied at commit. mutationType selects SET_VERSIONSTAMPED_KEY or SET_VERSIONSTAMPED_VALUE. The key or value (depending on type) must include the versionstamp placeholder bytes. Goroutine-safe via versionMu. Matches Java's FDBRecordContext.addVersionMutation(MutationType, key, value).

func (*FDBRecordContext) Cancel

func (rc *FDBRecordContext) Cancel()

Cancel cancels the transaction

func (*FDBRecordContext) CheckTransactionSize

func (rc *FDBRecordContext) CheckTransactionSize() error

CheckTransactionSize checks the approximate transaction size against the configured warning and error thresholds. Returns TransactionSizeExceededError if the error threshold is exceeded, TransactionSizeWarningError if the warning threshold is exceeded (once per transaction), or nil.

func (*FDBRecordContext) ClaimLocalVersion

func (rc *FDBRecordContext) ClaimLocalVersion() int

ClaimLocalVersion atomically claims the next local version number. Goroutine-safe via atomic.Int32 (matches Java's AtomicInteger.getAndIncrement()).

func (*FDBRecordContext) Commit

func (rc *FDBRecordContext) Commit() error

Commit commits the transaction

func (*FDBRecordContext) CommitWithHooks

func (rc *FDBRecordContext) CommitWithHooks() error

CommitWithHooks runs pre-commit checks, flushes pending version mutations, commits the FDB transaction, and runs post-commit callbacks. Use this instead of Commit() when the context was created manually (not via Run()).

func (*FDBRecordContext) CommitWithVersionstamp

func (rc *FDBRecordContext) CommitWithVersionstamp() ([]byte, error)

CommitWithVersionstamp commits the transaction, first running pre-commit checks, then flushing all queued versionstamp mutations. Returns the committed versionstamp (10 bytes) or nil for read-only transactions / no versionstamp mutations. Runs post-commit hooks after successful commit. Matches Java's FDBRecordContext.commitAsync() which always runs checks and hooks.

func (*FDBRecordContext) Context

func (rc *FDBRecordContext) Context() context.Context

Context returns the Go context

func (*FDBRecordContext) GetApproximateTransactionSize

func (rc *FDBRecordContext) GetApproximateTransactionSize() (int64, error)

GetApproximateTransactionSize returns the approximate size in bytes of the transaction's mutations so far. Useful for monitoring proximity to FDB's 10MB transaction size limit. Matches Java's FDBRecordContext.getApproximateTransactionSize().

func (*FDBRecordContext) GetConflictingKeys

func (rc *FDBRecordContext) GetConflictingKeys() []fdb.KeyRange

GetConflictingKeys attempts to identify conflicting keys after a commit failure. Reads the transaction's read conflict ranges. This is a best-effort diagnostic tool. Goroutine-safe via conflictMu. Matches Java's FDBRecordContext.reportConflictingKeys() (diagnostic, not exact).

func (*FDBRecordContext) GetLocalVersion

func (rc *FDBRecordContext) GetLocalVersion(versionKey []byte) (int, bool)

GetLocalVersion retrieves a cached local version for the given key. Returns (localVersion, true) if found, (0, false) otherwise. Goroutine-safe via versionMu.

func (*FDBRecordContext) GetMetaDataVersionStamp

func (rc *FDBRecordContext) GetMetaDataVersionStamp() ([]byte, error)

GetMetaDataVersionStamp reads the metadata version stamp at snapshot isolation. Returns nil if the stamp was written in this transaction (dirty) or doesn't exist. On ACCESSED_UNREADABLE errors (FDB code 1036), marks the stamp as dirty and returns nil. Goroutine-safe via atomic.Bool + goroutine-safe FDB transaction. Matches Java's FDBRecordContext.getMetaDataVersionStampAsync().

func (*FDBRecordContext) GetReadVersion

func (rc *FDBRecordContext) GetReadVersion() (int64, error)

GetReadVersion returns the transaction's read version. Matches Java's FDBRecordContext.getReadVersion().

func (*FDBRecordContext) HasDirtyStoreState

func (rc *FDBRecordContext) HasDirtyStoreState() bool

HasDirtyStoreState returns true if any store state was modified in this transaction. When true, cached store state should not be used. Goroutine-safe via atomic.Bool. Matches Java's FDBRecordContext.hasDirtyStoreState().

func (*FDBRecordContext) HasVersionMutations

func (rc *FDBRecordContext) HasVersionMutations() bool

HasVersionMutations returns true if there are pending version mutations. Goroutine-safe via versionMu.

func (*FDBRecordContext) PutSession

func (rc *FDBRecordContext) PutSession(key string, value any)

PutSession stores a transaction-scoped value under key. Matches Java's FDBRecordContext session storage; values die with the context.

func (*FDBRecordContext) RemoveLocalVersion

func (rc *FDBRecordContext) RemoveLocalVersion(versionKey []byte)

RemoveLocalVersion removes a cached local version entry. Goroutine-safe via versionMu.

func (*FDBRecordContext) RemoveLocalVersionsInRange

func (rc *FDBRecordContext) RemoveLocalVersionsInRange(begin, end fdb.Key)

RemoveLocalVersionsInRange removes all cached local versions whose key falls in [begin, end). Goroutine-safe via versionMu. Matches Java's FDBRecordContext.removeLocalVersionRange().

func (*FDBRecordContext) RemoveVersionMutation

func (rc *FDBRecordContext) RemoveVersionMutation(versionKey []byte)

RemoveVersionMutation removes a queued version mutation. Goroutine-safe via versionMu.

func (*FDBRecordContext) RemoveVersionMutationsInRange

func (rc *FDBRecordContext) RemoveVersionMutationsInRange(begin, end fdb.Key)

RemoveVersionMutationsInRange removes all queued version mutations whose key falls in [begin, end). Goroutine-safe via versionMu. Matches Java's FDBRecordContext.removeVersionMutationRange().

func (*FDBRecordContext) Session

func (rc *FDBRecordContext) Session(key string) any

Session returns the transaction-scoped value stored under key, or nil. Matches Java's FDBRecordContext.getSession.

func (*FDBRecordContext) SetDirtyStoreState

func (rc *FDBRecordContext) SetDirtyStoreState(dirty bool)

SetDirtyStoreState marks that store state was modified in this transaction. Goroutine-safe via atomic.Bool. Matches Java's FDBRecordContext.setDirtyStoreState().

func (*FDBRecordContext) SetMetaDataVersionStamp

func (rc *FDBRecordContext) SetMetaDataVersionStamp()

SetMetaDataVersionStamp schedules a SET_VERSIONSTAMPED_VALUE mutation on the metadata version key. After commit, this key will contain the commit versionstamp, which invalidates any cached store state entries with older stamps. Goroutine-safe via atomic.Bool + goroutine-safe FDB transaction. Matches Java's FDBRecordContext.setMetaDataVersionStamp().

func (*FDBRecordContext) SetReadVersion

func (rc *FDBRecordContext) SetReadVersion(version int64)

SetReadVersion sets the transaction's read version explicitly. Matches Java's FDBRecordContext.setReadVersion().

func (*FDBRecordContext) SetTimer

func (rc *FDBRecordContext) SetTimer(timer *StoreTimer)

SetTimer sets the instrumentation timer for this context. Goroutine-safe via atomic.Pointer. Matches Java's FDBRecordContext.setTimer().

func (*FDBRecordContext) SetTransactionPriority

func (rc *FDBRecordContext) SetTransactionPriority(priority TransactionPriority) error

SetTransactionPriority sets the priority for this transaction. Matches Java's FDBRecordContext applying FDBTransactionPriority.

func (*FDBRecordContext) Timer

func (rc *FDBRecordContext) Timer() *StoreTimer

Timer returns the instrumentation timer for this context, or nil if not set. Goroutine-safe via atomic.Pointer. Matches Java's FDBRecordContext.getTimer().

func (*FDBRecordContext) Transaction

func (rc *FDBRecordContext) Transaction() fdb.WritableTransaction

Transaction returns the underlying FDB transaction

func (*FDBRecordContext) TransactionID

func (rc *FDBRecordContext) TransactionID() int64

TransactionID returns a unique ID for this record context. Useful for logging and tracing. Matches Java's FDBRecordContext transaction ID.

func (*FDBRecordContext) UpdateVersionMutation

func (rc *FDBRecordContext) UpdateVersionMutation(mutationType VersionMutationType, versionKey []byte, value []byte, merge func(oldValue, newValue []byte) []byte)

UpdateVersionMutation queues or updates a versionstamp mutation with a merge function. If a mutation for the same key already exists, the merge function decides which value to keep. Goroutine-safe via versionMu. Matches Java's FDBRecordContext.updateVersionMutation(MutationType, key, value, BiFunction).

type FDBRecordStore

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

FDBRecordStore provides record storage operations within a transaction context. This is the main struct for storing and retrieving records.

func (*FDBRecordStore) AcquireReadLock

func (store *FDBRecordStore) AcquireReadLock(key string)

func (*FDBRecordStore) AcquireWriteLock

func (store *FDBRecordStore) AcquireWriteLock(key string)

lockRegistry delegation — matches Java's LockRegistry on FDBRecordContext.

func (*FDBRecordStore) AddBuildProgress

func (store *FDBRecordStore) AddBuildProgress(index *Index, count int64)

AddBuildProgress atomically increments the records-scanned counter for an index build. Matches Java's IndexingBase.tieredMergeAndCommit() → MutationType.ADD at IndexingSubspaces.indexBuildScannedRecordsSubspace().

func (*FDBRecordStore) AddRecordReadConflict

func (store *FDBRecordStore) AddRecordReadConflict(primaryKey tuple.Tuple) error

AddRecordReadConflict adds a read conflict range for the given primary key. This ensures that if another transaction modifies this record before this transaction commits, this transaction will fail with a conflict error.

Java equivalent: FDBRecordStore.addRecordReadConflict(Tuple primaryKey) Java location: fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/provider/foundationdb/FDBRecordStore.java:1222

func (*FDBRecordStore) AddRecordWriteConflict

func (store *FDBRecordStore) AddRecordWriteConflict(primaryKey tuple.Tuple) error

AddRecordWriteConflict adds a write conflict range for the given primary key. This ensures that if another transaction reads this record before this transaction commits, that transaction will fail with a conflict error.

Java equivalent: FDBRecordStore.addRecordWriteConflict(Tuple primaryKey) Java location: fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/provider/foundationdb/FDBRecordStore.java:1228

func (*FDBRecordStore) AddUniquenessViolation

func (store *FDBRecordStore) AddUniquenessViolation(index *Index, indexKey tuple.Tuple, primaryKey tuple.Tuple) error

AddUniquenessViolation records a uniqueness violation for the given index. Used during WRITE_ONLY index builds when a uniqueness conflict is detected. Stores empty bytes as the value (no cross-reference to conflicting PK). Use AddUniquenessViolationWithExisting to store the conflicting PK in the value.

func (*FDBRecordStore) AddUniquenessViolationWithExisting

func (store *FDBRecordStore) AddUniquenessViolationWithExisting(index *Index, indexKey tuple.Tuple, primaryKey tuple.Tuple, existingKey tuple.Tuple) error

AddUniquenessViolationWithExisting records a uniqueness violation with the conflicting PK. Matches Java's StandardIndexMaintainer.addUniquenessViolation(valueKey, primaryKey, existingKey). When existingKey is non-nil, its packed bytes are stored as the FDB value. When existingKey is nil, empty bytes are stored.

func (*FDBRecordStore) AsBuilder

func (store *FDBRecordStore) AsBuilder() *StoreBuilder

AsBuilder creates a new StoreBuilder pre-configured with this store's subspace, metadata, and index rebuild policy. Uses the same context. Matches Java's FDBRecordStore.asBuilder().

func (*FDBRecordStore) ClearAndMarkIndexWriteOnly

func (store *FDBRecordStore) ClearAndMarkIndexWriteOnly(indexName string) (bool, error)

ClearAndMarkIndexWriteOnly clears all index data and sets state to WRITE_ONLY. Used to start a fresh index rebuild. Matches Java's FDBRecordStore.clearAndMarkIndexWriteOnly().

func (*FDBRecordStore) ClearHeaderUserField

func (store *FDBRecordStore) ClearHeaderUserField(key string) error

ClearHeaderUserField removes a user-defined field from the store header. Goroutine-safe via stateMu (write lock). Matches Java's FDBRecordStore.clearHeaderUserField().

func (*FDBRecordStore) ClearStoreLockState

func (store *FDBRecordStore) ClearStoreLockState() error

ClearStoreLockState removes the lock state from the store header. Goroutine-safe via stateMu (write lock). Matches Java's FDBRecordStore.clearStoreLockStateAsync().

func (*FDBRecordStore) Context

func (store *FDBRecordStore) Context() *FDBRecordContext

Context returns the record context this store is using

func (*FDBRecordStore) CopyBuilder

func (store *FDBRecordStore) CopyBuilder(newContext *FDBRecordContext) *StoreBuilder

CopyBuilder creates a new StoreBuilder with this store's configuration but for a different context (transaction). Used to open the same store in a new transaction. Matches Java's FDBRecordStore.copyBuilder().

func (*FDBRecordStore) CountRecords

func (store *FDBRecordStore) CountRecords(
	ctx context.Context,
	low, high tuple.Tuple,
	lowEndpoint, highEndpoint EndpointType,
	continuation []byte,
	scanProperties ScanProperties,
) (int, error)

CountRecords counts records in a range by scanning the records subspace. Unlike GetRecordCount() which uses atomic counters, this actually scans records. Matches Java's FDBRecordStore.countRecords().

func (*FDBRecordStore) DeleteAllRecords

func (store *FDBRecordStore) DeleteAllRecords() error

DeleteAllRecords deletes all records from the store. Clears all data subspaces except StoreInfoKey (0) and IndexStateSpaceKey (5). Matches Java's FDBRecordStore.deleteAllRecords() which clears everything from records through index state begin, then from index state end through store end.

func (*FDBRecordStore) DeleteIndexEntries

func (store *FDBRecordStore) DeleteIndexEntries(index *Index)

DeleteIndexEntries clears all entries for the given index. Matches Java's StandardIndexMaintainer.deleteWhere() with no predicate.

func (*FDBRecordStore) DeleteIndexEntriesInRange

func (store *FDBRecordStore) DeleteIndexEntriesInRange(index *Index, prefix tuple.Tuple) error

DeleteIndexEntriesInRange clears index entries matching the given tuple prefix. For example, passing tuple.Tuple{"alice"} clears all entries where the first indexed value is "alice".

func (*FDBRecordStore) DeleteRecord

func (store *FDBRecordStore) DeleteRecord(primaryKey tuple.Tuple) (bool, error)

DeleteRecord deletes a record by its primary key, following Java's deleteRecordAsync semantics. Returns true if a record was deleted, false if no record existed with that key. Handles both split and unsplit records via SplitHelper. Matches Java's FDBRecordStore.deleteRecordAsync(Tuple primaryKey)

func (*FDBRecordStore) DeleteRecordsWhere

func (store *FDBRecordStore) DeleteRecordsWhere(prefix tuple.Tuple) error

DeleteRecordsWhere deletes all records whose primary key starts with the given prefix, along with all associated index entries, record versions, and record counts. This is a pure range-clear operation — no scanning.

The prefix must align with every active index's key expression so that index entries can be cleared via range operations. Type-specific indexes for matching types are cleared entirely. Universal indexes must have leading key expression columns that match the PK columns covered by the prefix.

Matches Java's FDBRecordStore.deleteRecordsWhereAsync().

func (*FDBRecordStore) DryRunDeleteRecord

func (store *FDBRecordStore) DryRunDeleteRecord(primaryKey tuple.Tuple) (bool, error)

DryRunDeleteRecord checks whether a record with the given primary key exists and could be deleted, without actually deleting it. Returns true if the record exists (and would be deleted), false if not found. Note: does NOT check store lock state, matching Java's dryRunDeleteRecordAsync which only loads the record without calling validateRecordUpdateAllowed. Matches Java's FDBRecordStore.dryRunDeleteRecordAsync().

func (*FDBRecordStore) DryRunSaveRecord

func (store *FDBRecordStore) DryRunSaveRecord(
	record proto.Message,
	existenceCheck RecordExistenceCheck,
) (*FDBStoredRecord[proto.Message], error)

DryRunSaveRecord validates a save and returns what the stored record would look like if saved, without actually writing data.

Scope — matches Java's FDBRecordStore.saveTypedRecord(isDryRun=true), which early-returns at FDBRecordStore.java:578 BEFORE the store-lock check (validateRecordUpdateAllowed, line 584), serializeAndSaveRecord (staging, line 586) and updateSecondaryIndexes (line 594). The PRIMARY-KEY existence/type checks run EARLIER (Java lines 561-577, before the isDryRun branch), so this keeps them. It deliberately does NOT validate store-lock state, does NOT stage the write, and does NOT run secondary-index maintenance. Consequences, all Java-faithful:

  • a DRY RUN on a FORBID_RECORD_UPDATE-locked store previews SUCCESS (the lock check is skipped — Java's early-return precedes it), and
  • a secondary-UNIQUE conflict is NOT detected in dry-run (only the real save's updateSecondaryIndexes catches it), and
  • a duplicate PK introduced WITHIN the same statement is not seen by a later row (no write is staged between rows).

Doing any of these would make Go's preview STRICTER than Java's — a conformance divergence (Go rejecting a DRY RUN that Java previews as success). Pinned by TestFDB_DmlDryRun_MatchesJavaLightweightValidation and TestFDB_DmlDryRun_LockedStorePreviews.

Matches Java's FDBRecordStore.dryRunSaveRecordAsync().

func (*FDBRecordStore) EstimateIndexSize

func (store *FDBRecordStore) EstimateIndexSize(index *Index) (int64, error)

EstimateIndexSize returns the estimated size in bytes of a specific index. Uses FDB's native GetEstimatedRangeSizeBytes on the index's subspace.

func (*FDBRecordStore) EstimateRecordsSize

func (store *FDBRecordStore) EstimateRecordsSize() (int64, error)

EstimateRecordsSize returns the estimated byte size of the records subspace only. Matches Java's FDBRecordStore.estimateRecordsSizeAsync().

func (*FDBRecordStore) EstimateRecordsSizeInRange

func (store *FDBRecordStore) EstimateRecordsSizeInRange(tupleRange TupleRange) (int64, error)

EstimateRecordsSizeInRange returns the estimated size in bytes of records within the given tuple range. Uses FDB's native GetEstimatedRangeSizeBytes. Matches Java's FDBRecordStore.estimateRecordsSizeAsync(TupleRange).

func (*FDBRecordStore) EstimateStoreSize

func (store *FDBRecordStore) EstimateStoreSize() (int64, error)

EstimateStoreSize returns the estimated byte size of the entire store subspace. Uses FDB's GetEstimatedRangeSizeBytes which provides an approximation. Matches Java's FDBRecordStore.estimateStoreSizeAsync().

func (*FDBRecordStore) EvaluateAggregateFunction

func (store *FDBRecordStore) EvaluateAggregateFunction(
	ctx context.Context,
	recordTypeNames []string,
	fn *IndexAggregateFunction,
	scanRange TupleRange,
	isolationLevel IsolationLevel,
) (tuple.Tuple, error)

EvaluateAggregateFunction evaluates an aggregate function using the best matching index. Returns the aggregate result as a tuple, or nil if no matching entries exist.

For COUNT/SUM indexes: scans all group entries and reduces them. For MIN_EVER/MAX_EVER indexes: scans all group entries and reduces them. For VALUE indexes with MIN/MAX: scans 1 entry in the right direction.

Matches Java's FDBRecordStore.evaluateAggregateFunction().

func (*FDBRecordStore) EvaluateRecordFunction

func (store *FDBRecordStore) EvaluateRecordFunction(
	fn *IndexRecordFunction,
	record *FDBStoredRecord[proto.Message],
) (*int64, error)

EvaluateRecordFunction evaluates an index record function for a specific record. For RANK indexes, this returns the rank of the record's score within its group. Returns nil if the record's value is not in the index (e.g. null field).

Matches Java's FDBRecordStore.evaluateIndexRecordFunction().

func (*FDBRecordStore) EvaluateStoreFunction

func (store *FDBRecordStore) EvaluateStoreFunction(
	fn *StoreRecordFunction,
	record *FDBStoredRecord[proto.Message],
) (any, error)

EvaluateStoreFunction evaluates a store-level function on a record. Unlike EvaluateRecordFunction (which uses indexes), store functions access store state directly.

Currently supported functions:

  • "version": returns the record's FDBRecordVersion (nil if none)

Matches Java's FDBRecordStore.evaluateStoreFunction().

func (*FDBRecordStore) FirstUnbuiltRange

func (store *FDBRecordStore) FirstUnbuiltRange(index *Index) (*RangeSetRange, error)

FirstUnbuiltRange returns the first range of the index that hasn't been built yet. Returns nil, nil if the index is fully built. Matches Java's FDBRecordStore.firstUnbuiltRange(index).

func (*FDBRecordStore) GetAllIndexStates

func (store *FDBRecordStore) GetAllIndexStates() map[string]IndexState

GetAllIndexStates returns a map of all index names to their current states. Indexes without an explicit state entry default to READABLE. Matches Java's FDBRecordStore.getAllIndexStates().

func (*FDBRecordStore) GetAllIndexStatesMap

func (store *FDBRecordStore) GetAllIndexStatesMap() map[string]IndexState

GetAllIndexStatesMap returns a copy of the raw index states map (non-READABLE only). Goroutine-safe via stateMu (read lock). For a complete map including defaulted READABLE states, use GetAllIndexStates().

func (*FDBRecordStore) GetContext

func (store *FDBRecordStore) GetContext() *FDBRecordContext

GetContext returns the record context (transaction wrapper) for this store. Matches Java's FDBRecordStore.getRecordContext().

func (*FDBRecordStore) GetDisabledIndexes

func (store *FDBRecordStore) GetDisabledIndexes() []*Index

GetDisabledIndexes returns all indexes that are in DISABLED state. These indexes are not maintained or readable. Matches Java's FDBRecordStoreBase.getDisabledIndexes() (derived from getAllIndexStates).

func (*FDBRecordStore) GetEnabledIndexes

func (store *FDBRecordStore) GetEnabledIndexes() []*Index

GetEnabledIndexes returns all indexes that are NOT in DISABLED state. Matches Java's FDBRecordStoreBase.getEnabledIndexes().

func (*FDBRecordStore) GetEnabledUniversalIndexes

func (store *FDBRecordStore) GetEnabledUniversalIndexes() []*Index

GetEnabledUniversalIndexes returns universal indexes NOT in DISABLED state. Matches Java's FDBRecordStore.getEnabledUniversalIndexes().

func (*FDBRecordStore) GetFormatVersion

func (store *FDBRecordStore) GetFormatVersion() int32

GetFormatVersion returns the store format version. Goroutine-safe via stateMu (read lock). Matches Java's FDBRecordStore.getFormatVersion().

func (*FDBRecordStore) GetHeaderUserField

func (store *FDBRecordStore) GetHeaderUserField(key string) []byte

GetHeaderUserField returns a user-defined field from the store header. Returns nil if the field is not set. Goroutine-safe via stateMu (read lock). Matches Java's FDBRecordStore.getHeaderUserField().

func (*FDBRecordStore) GetIncarnation

func (store *FDBRecordStore) GetIncarnation() int32

GetIncarnation returns the incarnation counter from the store header. Used for cross-cluster data migration versioning. Goroutine-safe via stateMu (read lock). Matches Java's FDBRecordStore.getIncarnation().

func (*FDBRecordStore) GetIndexMaintainer

func (store *FDBRecordStore) GetIndexMaintainer(index *Index) (IndexMaintainer, error)

GetIndexMaintainer returns the index maintainer for the given index. Matches Java's FDBRecordStore.getIndexMaintainer().

func (*FDBRecordStore) GetIndexState

func (store *FDBRecordStore) GetIndexState(indexName string) IndexState

GetIndexState returns the state of the given index. Returns READABLE if no explicit state is stored (matching Java's default behavior). Goroutine-safe via stateMu (read lock).

func (*FDBRecordStore) GetIndexesToBuildSince

func (store *FDBRecordStore) GetIndexesToBuildSince(version int) []*Index

GetIndexesToBuildSince returns all indexes that need to be built because they were added or modified since the given metadata version. Matches Java's FDBRecordStore.getIndexesToBuildSince(version).

func (*FDBRecordStore) GetKeySizeLimit

func (store *FDBRecordStore) GetKeySizeLimit() int

GetKeySizeLimit returns the maximum key size in bytes for index entries. Matches Java's FDBRecordStore.getKeySizeLimit().

func (*FDBRecordStore) GetMetaData

func (store *FDBRecordStore) GetMetaData() *RecordMetaData

GetMetaData returns the metadata for this store. Matches Java's FDBRecordStore.getRecordMetaData().

func (*FDBRecordStore) GetMetaDataVersion

func (store *FDBRecordStore) GetMetaDataVersion() int32

GetMetaDataVersion returns the metadata version stored in the header. Goroutine-safe via stateMu (read lock).

func (*FDBRecordStore) GetRangeSplitPoints

func (store *FDBRecordStore) GetRangeSplitPoints(chunkSize int64) ([]fdb.Key, error)

GetRangeSplitPoints returns split points that divide the store's records subspace into approximately equal-sized chunks of the given byte size. Useful for parallelizing scans across multiple transactions. Uses FDB's native GetRangeSplitPoints which is efficient for large datasets.

func (*FDBRecordStore) GetReadableIndexes

func (store *FDBRecordStore) GetReadableIndexes() []*Index

GetReadableIndexes returns all indexes that are in READABLE or READABLE_UNIQUE_PENDING state. Matches Java's FDBRecordStoreBase.getReadableIndexes().

func (*FDBRecordStore) GetReadableUniversalIndexes

func (store *FDBRecordStore) GetReadableUniversalIndexes() []*Index

GetReadableUniversalIndexes returns universal indexes in READABLE state. Matches Java's FDBRecordStore.getReadableUniversalIndexes().

func (*FDBRecordStore) GetRecordCount

func (store *FDBRecordStore) GetRecordCount() (int64, error)

GetRecordCount returns the total count across all groups by reading the count for the evaluated count key of the given record. For ungrouped counting, this returns the total count.

func (*FDBRecordStore) GetRecordMetaData

func (store *FDBRecordStore) GetRecordMetaData() *RecordMetaData

GetRecordMetaData returns the metadata associated with this store. Matches Java's FDBRecordStore.getRecordMetaData().

func (*FDBRecordStore) GetRecordStoreState

func (store *FDBRecordStore) GetRecordStoreState() *RecordStoreState

GetRecordStoreState returns the current state of the store (header + index states). Goroutine-safe via stateMu (read lock). Matches Java's FDBRecordStore.getRecordStoreState().

func (*FDBRecordStore) GetSnapshotRecordCount

func (store *FDBRecordStore) GetSnapshotRecordCount(countKey tuple.Tuple) (int64, error)

GetSnapshotRecordCount returns the count of records matching the given key. Uses snapshot reads (non-conflicting) matching Java's getSnapshotRecordCount(). Only allowed when RecordCountState is READABLE.

For ungrouped counting (EmptyKeyExpression), pass an empty tuple. For per-type counting, pass a tuple with the record type name/index.

Returns 0 if no count exists (null in FDB means 0, matching Java).

func (*FDBRecordStore) GetSnapshotRecordCountForRecordType

func (store *FDBRecordStore) GetSnapshotRecordCountForRecordType(recordTypeName string) (int64, error)

GetSnapshotRecordCountForRecordType returns the count of records for a specific record type. Requires that the metadata uses RecordTypeKeyExpression as the count key. Matches Java's getSnapshotRecordCountForRecordType().

func (*FDBRecordStore) GetStoreHeader

func (store *FDBRecordStore) GetStoreHeader() *gen.DataStoreInfo

GetStoreHeader returns a copy of the current store header proto. Goroutine-safe via stateMu (read lock). Matches Java's FDBRecordStore.getRecordStoreState().getStoreHeader().

func (*FDBRecordStore) GetSubspace

func (store *FDBRecordStore) GetSubspace() subspace.Subspace

GetSubspace returns the FDB subspace for this store. Matches Java's FDBRecordStore.getSubspace().

func (*FDBRecordStore) GetUserVersion

func (store *FDBRecordStore) GetUserVersion() int32

GetUserVersion returns the user-defined store version. Goroutine-safe via stateMu (read lock). Matches Java's FDBRecordStore.getUserVersion().

func (*FDBRecordStore) GetValueSizeLimit

func (store *FDBRecordStore) GetValueSizeLimit() int

GetValueSizeLimit returns the maximum value size in bytes for index entries. Matches Java's FDBRecordStore.getValueSizeLimit().

func (*FDBRecordStore) GetWriteOnlyIndexes

func (store *FDBRecordStore) GetWriteOnlyIndexes() []*Index

GetWriteOnlyIndexes returns all indexes that are in WRITE_ONLY state. These are indexes currently being built by an OnlineIndexer. Matches Java's FDBRecordStoreBase.getWriteOnlyIndexes() (derived from getAllIndexStates).

func (*FDBRecordStore) IndexSecondarySubspace

func (store *FDBRecordStore) IndexSecondarySubspace(index *Index) subspace.Subspace

IndexSecondarySubspace returns the secondary subspace for a specific index. Matches Java's FDBRecordStore.indexSecondarySubspace(index).

func (*FDBRecordStore) IndexStateSubspace

func (store *FDBRecordStore) IndexStateSubspace() subspace.Subspace

IndexStateSubspace returns the subspace where index states are stored. Matches Java's FDBRecordStore.indexStateSubspace().

func (*FDBRecordStore) IndexSubspace

func (store *FDBRecordStore) IndexSubspace(index *Index) subspace.Subspace

IndexSubspace returns the subspace for a specific index's entries. Matches Java's FDBRecordStore.indexSubspace(index).

func (*FDBRecordStore) InsertRecord

func (store *FDBRecordStore) InsertRecord(record proto.Message) (*FDBStoredRecord[proto.Message], error)

InsertRecord saves a record and throws an error if it already exists. This is equivalent to SaveRecordWithOptions(record, RecordExistenceCheckErrorIfExists).

Java equivalent: FDBRecordStore.insertRecordAsync(Message rec) Java location: fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/provider/foundationdb/FDBRecordStoreBase.java:629

Returns:

  • *FDBStoredRecord: The saved record with metadata
  • error: RecordAlreadyExistsError if a record with the same primary key already exists

func (*FDBRecordStore) IsCacheable

func (store *FDBRecordStore) IsCacheable() bool

IsCacheable returns whether the store state is marked as cacheable in the header. Goroutine-safe via stateMu (read lock). Matches Java's FDBRecordStore.getRecordStoreState().getStoreHeader().getCacheable().

func (*FDBRecordStore) IsIndexDisabled

func (store *FDBRecordStore) IsIndexDisabled(indexName string) bool

IsIndexDisabled returns true if the index is in DISABLED state.

func (*FDBRecordStore) IsIndexReadable

func (store *FDBRecordStore) IsIndexReadable(indexName string) bool

IsIndexReadable returns true if the index is in READABLE state.

func (*FDBRecordStore) IsIndexReadableUniquePending

func (store *FDBRecordStore) IsIndexReadableUniquePending(indexName string) bool

IsIndexReadableUniquePending returns true if the index is in READABLE_UNIQUE_PENDING state. This state means the unique index is fully indexed but may have duplicate entries. Matches Java's FDBRecordStoreBase.isIndexReadableUniquePending().

func (*FDBRecordStore) IsIndexScannable

func (store *FDBRecordStore) IsIndexScannable(indexName string) bool

IsIndexScannable returns true if the index can be scanned (READABLE or READABLE_UNIQUE_PENDING).

func (*FDBRecordStore) IsIndexWriteOnly

func (store *FDBRecordStore) IsIndexWriteOnly(indexName string) bool

IsIndexWriteOnly returns true if the index is in WRITE_ONLY state.

func (*FDBRecordStore) IsStateCacheable

func (store *FDBRecordStore) IsStateCacheable() bool

IsStateCacheable returns whether this store's state is currently cacheable. Goroutine-safe via stateMu (read lock).

func (*FDBRecordStore) IsVersionChanged

func (store *FDBRecordStore) IsVersionChanged() bool

IsVersionChanged returns true if the metadata version changed during the most recent Open/CreateOrOpen (i.e., checkPossiblyRebuild detected that the stored version < current metadata version). Matches Java's FDBRecordStore.isVersionChanged().

func (*FDBRecordStore) LoadBuildProgress

func (store *FDBRecordStore) LoadBuildProgress(index *Index) (int64, error)

LoadBuildProgress reads the records-scanned counter for an index build. Returns 0 if no progress has been tracked. Matches Java's IndexBuildState.loadRecordsScannedAsync().

func (*FDBRecordStore) LoadIndexingTypeStamp

func (store *FDBRecordStore) LoadIndexingTypeStamp(index *Index) (*gen.IndexBuildIndexingStamp, error)

LoadIndexingTypeStamp loads the indexing method stamp for an index. Returns nil if no stamp exists. Matches Java's FDBRecordStore.loadIndexingTypeStampAsync().

func (*FDBRecordStore) LoadRecord

func (store *FDBRecordStore) LoadRecord(primaryKey tuple.Tuple) (*FDBStoredRecord[proto.Message], error)

LoadRecord loads a record by its primary key. Handles both unsplit (suffix 0) and split (suffixes 1, 2, ...) records via SplitHelper, matching Java's FDBRecordStore.loadRecordAsync().

func (*FDBRecordStore) LoadRecordVersion

func (store *FDBRecordStore) LoadRecordVersion(primaryKey tuple.Tuple, snapshot bool) (*FDBRecordVersion, error)

LoadRecordVersion loads the version associated with a record. Returns nil if no version is stored or versioning is not enabled. Matches Java's FDBRecordStore.loadRecordVersionAsync().

func (*FDBRecordStore) MarkIndexDisabled

func (store *FDBRecordStore) MarkIndexDisabled(indexName string) (bool, error)

MarkIndexDisabled transitions an index to DISABLED state and clears all index data. Returns true if the state was changed. Matches Java's FDBRecordStore.markIndexDisabled().

func (*FDBRecordStore) MarkIndexReadable

func (store *FDBRecordStore) MarkIndexReadable(indexName string) (bool, error)

MarkIndexReadable transitions an index to READABLE state. Returns true if the state was changed, false if already READABLE. Returns an error if the index is not fully built or if a unique index has violations. Matches Java's FDBRecordStore.markIndexReadable(index, allowUniquePending=false).

func (*FDBRecordStore) MarkIndexReadableOrUniquePending

func (store *FDBRecordStore) MarkIndexReadableOrUniquePending(indexName string) (bool, error)

MarkIndexReadableOrUniquePending transitions a unique index to READABLE if it has no uniqueness violations, or to READABLE_UNIQUE_PENDING if violations exist. For non-unique indexes, always transitions to READABLE. Returns true if the state was changed. Returns an error if the index is not fully built. Matches Java's FDBRecordStore.markIndexReadableOrUniquePending().

func (*FDBRecordStore) MarkIndexWriteOnly

func (store *FDBRecordStore) MarkIndexWriteOnly(indexName string) (bool, error)

MarkIndexWriteOnly transitions an index to WRITE_ONLY state. Returns true if the state was changed. Matches Java's FDBRecordStore.markIndexWriteOnly().

func (*FDBRecordStore) OverrideLockSaveRecord

func (store *FDBRecordStore) OverrideLockSaveRecord(
	record proto.Message,
	existenceCheck RecordExistenceCheck,
) (*FDBStoredRecord[proto.Message], error)

OverrideLockSaveRecord saves a record even when the store is locked for record updates (FORBID_RECORD_UPDATE). This is used by the OnlineIndexer to write index maintenance records while the store is locked. Goroutine-safe: uses parameter-based override instead of mutable field. Matches Java's FDBRecordStore.overrideLockSaveRecordAsync().

func (*FDBRecordStore) RebuildAllIndexes

func (store *FDBRecordStore) RebuildAllIndexes() error

RebuildAllIndexes rebuilds all indexes that are not in READABLE state. Matches Java's FDBRecordStore.rebuildAllIndexes().

func (*FDBRecordStore) RebuildIndex

func (store *FDBRecordStore) RebuildIndex(index *Index) error

RebuildIndex rebuilds an index within the current transaction. Clears existing index data, scans all records, and re-indexes them. Upon completion, the index is marked READABLE.

Because this runs in a single transaction, it is limited by FDB's 5-second time limit and 10MB transaction size. For large stores, use OnlineIndexer.BuildIndex() which splits work across transactions.

Matches Java's FDBRecordStore.rebuildIndex() which delegates to IndexingBase.rebuildIndexAsync() for the in-transaction path.

func (*FDBRecordStore) RecordExists

func (store *FDBRecordStore) RecordExists(primaryKey tuple.Tuple, isolationLevel IsolationLevel) (bool, error)

RecordExists checks if a record exists with the given primary key. Handles both split and unsplit records via SplitHelper.

Java equivalent: FDBRecordStore.recordExistsAsync(Tuple primaryKey, IsolationLevel isolationLevel)

func (*FDBRecordStore) RecordsSubspace

func (store *FDBRecordStore) RecordsSubspace() subspace.Subspace

RecordsSubspace returns the subspace where records are stored. Matches Java's FDBRecordStore.recordsSubspace().

func (*FDBRecordStore) ReleaseReadLock

func (store *FDBRecordStore) ReleaseReadLock(key string)

func (*FDBRecordStore) ReleaseWriteLock

func (store *FDBRecordStore) ReleaseWriteLock(key string)

func (*FDBRecordStore) ReloadRecordStoreState

func (store *FDBRecordStore) ReloadRecordStoreState() error

ReloadRecordStoreState forces a reload of the store state from FDB. Useful when another transaction may have changed the state. Goroutine-safe via stateMu (write lock). Matches Java's FDBRecordStore.loadRecordStoreStateAsync() force reload path.

func (*FDBRecordStore) ResolveUniquenessViolation

func (store *FDBRecordStore) ResolveUniquenessViolation(index *Index, indexKey tuple.Tuple, primaryKey tuple.Tuple) error

ResolveUniquenessViolation removes a single uniqueness violation entry. Call this after manually resolving the conflict (e.g., deleting the duplicate record). Matches Java's StandardIndexMaintainer.resolveUniquenessViolation().

func (*FDBRecordStore) ResolveUniquenessViolationByDeletion

func (store *FDBRecordStore) ResolveUniquenessViolationByDeletion(
	index *Index,
	valueKey tuple.Tuple,
	remainPrimaryKey tuple.Tuple,
) error

ResolveUniquenessViolationByDeletion resolves uniqueness violations for a specific index value key by deleting all records that violate uniqueness, except for the record with remainPrimaryKey (if non-nil). If remainPrimaryKey is nil, all violating records are deleted. Matches Java's FDBRecordStore.resolveUniquenessViolation(index, valueKey, remainPrimaryKey).

func (*FDBRecordStore) SaveIndexingTypeStamp

func (store *FDBRecordStore) SaveIndexingTypeStamp(index *Index, stamp *gen.IndexBuildIndexingStamp) error

SaveIndexingTypeStamp persists the indexing method stamp for an index. Matches Java's FDBRecordStore.saveIndexingTypeStamp().

func (*FDBRecordStore) SaveRecord

func (store *FDBRecordStore) SaveRecord(record proto.Message) (*FDBStoredRecord[proto.Message], error)

SaveRecord saves a protobuf record to the store. Equivalent to SaveRecordWithOptions(record, RecordExistenceCheckNone). Java equivalent: FDBRecordStore.saveRecord(Message rec)

func (*FDBRecordStore) SaveRecordBatch

func (store *FDBRecordStore) SaveRecordBatch(
	records []proto.Message,
) ([]*FDBStoredRecord[proto.Message], error)

SaveRecordBatch saves multiple records with pipelined existence checks.

Instead of N sequential blocking FDB reads (one per record in SaveRecord), this method issues all existence-check Gets up front as futures, then collects them in one batch. This turns N round trips into ~1 round trip for the existence checks, significantly improving throughput for batch inserts.

Semantically equivalent to calling SaveRecord N times. All records are saved in the current transaction.

func (*FDBRecordStore) SaveRecordWithOptions

func (store *FDBRecordStore) SaveRecordWithOptions(
	record proto.Message,
	existenceCheck RecordExistenceCheck,
) (*FDBStoredRecord[proto.Message], error)

SaveRecordWithOptions saves a protobuf record with existence checking. This is the full-featured save method that supports all RecordExistenceCheck modes.

Java equivalent: FDBRecordStore.saveRecordAsync(Message rec, RecordExistenceCheck existenceCheck, FDBRecordVersion version, VersionstampSaveBehavior behavior) Java location: fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/provider/foundationdb/FDBRecordStore.java:496

Parameters:

  • record: The protobuf message to save
  • existenceCheck: Validation to perform (NONE, ERROR_IF_EXISTS, etc.)

Returns:

  • *FDBStoredRecord: The saved record with metadata
  • error: RecordAlreadyExistsError, RecordDoesNotExistError, or RecordTypeChangedError based on existenceCheck

Note: Version and versionstamp support will be added in Phase 2

func (*FDBRecordStore) ScanIndex

func (store *FDBRecordStore) ScanIndex(
	index *Index,
	scanRange TupleRange,
	continuation []byte,
	scanProperties ScanProperties,
) RecordCursor[*IndexEntry]

ScanIndex scans a secondary index and returns a cursor over IndexEntry results. Returns an error cursor if the index is not in a scannable state (DISABLED or WRITE_ONLY). Dispatches to the appropriate maintainer's Scan() method (VALUE vs COUNT). Matches Java's FDBRecordStore.scanIndex().

func (*FDBRecordStore) ScanIndexByType

func (store *FDBRecordStore) ScanIndexByType(
	index *Index,
	scanType IndexScanType,
	scanRange TupleRange,
	continuation []byte,
	scanProperties ScanProperties,
) RecordCursor[*IndexEntry]

ScanIndexByType scans a secondary index with an explicit scan type. For BY_VALUE, delegates to the maintainer's Scan. For BY_RANK, converts rank range to score range and scans the B-tree. Matches Java's FDBRecordStore.scanIndex(index, scanType, range, ...).

func (*FDBRecordStore) ScanIndexRecords

func (store *FDBRecordStore) ScanIndexRecords(
	indexName string,
	scanRange TupleRange,
	continuation []byte,
	scanProperties ScanProperties,
) RecordCursor[*FDBIndexedRecord]

ScanIndexRecords scans a secondary index and fetches the actual records. For each index entry, it loads the record by primary key. Orphan index entries (pointing to deleted records) are skipped. Matches Java's FDBRecordStore.scanIndexRecords().

func (*FDBRecordStore) ScanRecordKeys

func (store *FDBRecordStore) ScanRecordKeys(
	continuation []byte,
	scanProperties ScanProperties,
) RecordCursor[tuple.Tuple]

ScanRecordKeys scans only the primary keys of records without deserializing record data. This is significantly faster than ScanRecords when you only need the keys (avoids protobuf deserialization overhead). Split records (multiple KV entries per PK) are automatically deduplicated. Matches Java's FDBRecordStore.scanRecordKeys().

func (*FDBRecordStore) ScanRecords

func (store *FDBRecordStore) ScanRecords(continuation []byte, scanProperties ScanProperties) RecordCursor[*FDBStoredRecord[proto.Message]]

ScanRecords scans all records in the store. For forward scans, continuation sets the low endpoint (start after last returned key). For reverse scans, continuation sets the high endpoint (end before last returned key). Matches Java's KeyValueCursorBase behavior.

func (*FDBRecordStore) ScanRecordsByType

func (store *FDBRecordStore) ScanRecordsByType(recordTypeName string, continuation []byte, scanProperties ScanProperties) RecordCursor[*FDBStoredRecord[proto.Message]]

ScanRecordsByType scans records filtered to a specific record type. When the primary key uses RecordTypeKey() as its first component (common pattern), this does a prefix scan on just that type's range — O(records of this type) instead of O(all records). Falls back to full scan + filter if RecordTypeKey is not used. Matches Java's RecordQuery with RecordTypeFilter.

func (*FDBRecordStore) ScanRecordsInRange

func (store *FDBRecordStore) ScanRecordsInRange(
	low, high tuple.Tuple,
	lowEndpoint, highEndpoint EndpointType,
	continuation []byte,
	scanProperties ScanProperties,
) RecordCursor[*FDBStoredRecord[proto.Message]]

ScanRecordsInRange scans records in a key range

func (*FDBRecordStore) ScanTimeWindowLeaderboard

func (store *FDBRecordStore) ScanTimeWindowLeaderboard(
	index *Index,
	scanType IndexScanType,
	leaderboardType int,
	leaderboardTimestamp int64,
	scanRange TupleRange,
	continuation []byte,
	scanProperties ScanProperties,
) RecordCursor[*IndexEntry]

ScanTimeWindowLeaderboard scans a TIME_WINDOW_LEADERBOARD index within a specific time window. The scanType determines how the range is interpreted:

  • BY_TIME_WINDOW / BY_VALUE: scanRange contains score bounds
  • BY_RANK: scanRange contains rank bounds (converted to score bounds via RankedSet)

Matches Java's FDBRecordStore.scanIndex() with TimeWindowScanRange.

func (*FDBRecordStore) ScanUniquenessViolations

func (store *FDBRecordStore) ScanUniquenessViolations(index *Index) ([]UniquenessViolation, error)

ScanUniquenessViolations returns all uniqueness violations recorded for the given index. Violations are stored in the IndexUniquenessViolationsKey (7) subspace. Matches Java's StandardIndexMaintainer.scanUniquenessViolations().

func (*FDBRecordStore) ScanUniquenessViolationsForValue

func (store *FDBRecordStore) ScanUniquenessViolationsForValue(
	index *Index,
	valueKey tuple.Tuple,
) ([]UniquenessViolation, error)

ScanUniquenessViolationsForValue returns uniqueness violations for a specific index value key. This filters violations to only those matching the given value key. Matches Java's StandardIndexMaintainer.scanUniquenessViolations(index, valueKey).

func (*FDBRecordStore) ScanVectorIndex

func (store *FDBRecordStore) ScanVectorIndex(
	index *Index,
	queryVector []float64,
	k int,
	efSearch int,
	continuation []byte,
	scanProperties ScanProperties,
) RecordCursor[*IndexEntry]

ScanVectorIndex scans a VECTOR index with BY_DISTANCE semantics, returning results as a cursor. This is the cursor-based API matching Java's VectorIndexMaintainer.scan(VectorIndexScanBounds, ...).

Each result is an IndexEntry with Key = primaryKey and Value = tuple{distance}. Results are sorted by distance (closest first).

For prefix-partitioned indexes, use ScanVectorIndexWithPrefix instead.

func (*FDBRecordStore) ScanVectorIndexWithPrefix

func (store *FDBRecordStore) ScanVectorIndexWithPrefix(
	index *Index,
	prefix tuple.Tuple,
	queryVector []float64,
	k int,
	efSearch int,
	continuation []byte,
	scanProperties ScanProperties,
) RecordCursor[*IndexEntry]

ScanVectorIndexWithPrefix scans a VECTOR index with BY_DISTANCE semantics, scoped to a specific prefix partition. Pass nil prefix for non-grouped indexes.

Each result is an IndexEntry with Key = primaryKey and Value = tuple{distance}. Results are sorted by distance (closest first).

func (*FDBRecordStore) SearchVectorIndex

func (store *FDBRecordStore) SearchVectorIndex(
	index *Index,
	queryVector []float64,
	k int,
	efSearch int,
) ([]VectorSearchResult, error)

SearchVectorIndex performs a k-nearest-neighbor search on a VECTOR index. Matches Java's VectorIndexMaintainer scan with VectorIndexScanBounds.

For prefix-partitioned indexes, use SearchVectorIndexWithPrefix instead.

func (*FDBRecordStore) SearchVectorIndexRecords

func (store *FDBRecordStore) SearchVectorIndexRecords(
	ctx context.Context,
	index *Index,
	queryVector []float64,
	k int,
	efSearch int,
) ([]*FDBIndexedRecord, error)

SearchVectorIndexRecords performs a kNN search and fetches the corresponding records.

For prefix-partitioned indexes, use SearchVectorIndexRecordsWithPrefix instead.

func (*FDBRecordStore) SearchVectorIndexRecordsWithPrefix

func (store *FDBRecordStore) SearchVectorIndexRecordsWithPrefix(
	ctx context.Context,
	index *Index,
	prefix tuple.Tuple,
	queryVector []float64,
	k int,
	efSearch int,
) ([]*FDBIndexedRecord, error)

SearchVectorIndexRecordsWithPrefix performs a kNN search scoped to a prefix partition and fetches the corresponding records.

func (*FDBRecordStore) SearchVectorIndexWithPrefix

func (store *FDBRecordStore) SearchVectorIndexWithPrefix(
	index *Index,
	prefix tuple.Tuple,
	queryVector []float64,
	k int,
	efSearch int,
) ([]VectorSearchResult, error)

SearchVectorIndexWithPrefix performs a k-nearest-neighbor search on a VECTOR index, scoped to a specific prefix partition. Pass nil prefix for non-grouped indexes.

func (*FDBRecordStore) SetFormatVersion

func (store *FDBRecordStore) SetFormatVersion(version int32) error

SetFormatVersion updates the store's format version in the header. This is used during store migration to enable new features. Matches Java's FDBRecordStore.setFormatVersion().

func (*FDBRecordStore) SetHeaderUserField

func (store *FDBRecordStore) SetHeaderUserField(key string, value []byte) error

SetHeaderUserField sets a user-defined field in the store header. The value is persisted immediately. Keep values small since the entire header is loaded on every store open. Goroutine-safe via stateMu (write lock). Matches Java's FDBRecordStore.setHeaderUserField().

func (*FDBRecordStore) SetStateCacheability

func (store *FDBRecordStore) SetStateCacheability(cacheable bool) (bool, error)

SetStateCacheability sets whether this store's state can be cached across transactions. When enabled, the metadata version stamp is initialized so cache invalidation can work. Requires FormatVersion >= CACHEABLE_STATE (7). Returns true if the cacheability was changed, false if already at the desired state. Goroutine-safe via stateMu (write lock). Matches Java's FDBRecordStore.setStateCacheabilityAsync().

func (*FDBRecordStore) SetStoreLockState

func (store *FDBRecordStore) SetStoreLockState(state gen.DataStoreInfo_StoreLockState_State, reason string) error

SetStoreLockState sets the store lock state in the header and persists it. Use FORBID_RECORD_UPDATE to prevent record mutations, or FULL_STORE to prevent the store from being opened entirely. Goroutine-safe via stateMu (write lock). Matches Java's FDBRecordStore.setStoreLockStateAsync().

func (*FDBRecordStore) SetUserVersion

func (store *FDBRecordStore) SetUserVersion(version int32) error

SetUserVersion updates the user-defined store version and writes it to FDB. Goroutine-safe via stateMu (write lock). Matches Java's FDBRecordStore.setUserVersion().

func (*FDBRecordStore) Subspace

func (store *FDBRecordStore) Subspace() subspace.Subspace

Subspace returns the subspace this store is using

func (*FDBRecordStore) UpdateIncarnation

func (store *FDBRecordStore) UpdateIncarnation(updater func(current int32) int32) error

UpdateIncarnation atomically updates the incarnation counter using the provided function. The new value must be strictly greater than the current value. Goroutine-safe via stateMu (write lock). Matches Java's FDBRecordStore.updateIncarnation().

func (*FDBRecordStore) UpdateRecord

func (store *FDBRecordStore) UpdateRecord(record proto.Message) (*FDBStoredRecord[proto.Message], error)

UpdateRecord saves a record and throws an error if it does not already exist or if its type has changed. This is equivalent to SaveRecordWithOptions(record, RecordExistenceCheckErrorIfNotExistsOrTypeChanged).

Java equivalent: FDBRecordStore.updateRecordAsync(Message rec) Java location: fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/provider/foundationdb/FDBRecordStoreBase.java:649

Returns:

  • *FDBStoredRecord: The saved record with metadata
  • error: RecordDoesNotExistError if no record exists with this primary key
  • error: RecordTypeChangedError if an existing record has a different type

func (*FDBRecordStore) UpdateRecordCountState

func (store *FDBRecordStore) UpdateRecordCountState(newState gen.DataStoreInfo_RecordCountState) error

UpdateRecordCountState transitions the record count state. Valid transitions: READABLE↔WRITE_ONLY, any→DISABLED. DISABLED is terminal. When transitioning to DISABLED, clears all count data. Goroutine-safe via stateMu (write lock). Matches Java's FDBRecordStore.updateRecordCountStateAsync().

func (*FDBRecordStore) VacuumReadableIndexesBuildData

func (store *FDBRecordStore) VacuumReadableIndexesBuildData()

VacuumReadableIndexesBuildData clears build artifacts (range sets, stamps, progress counters) for indexes that are already READABLE. Matches Java's FDBRecordStore.vacuumReadableIndexesBuildData().

func (*FDBRecordStore) ValidateIndex

func (store *FDBRecordStore) ValidateIndex(ctx context.Context, index *Index) (*IndexValidationResult, error)

ValidateIndex checks the consistency of an index against the actual records. Detects missing entries (record exists but index entry missing) and orphaned entries (index entry exists but no corresponding record). Matches Java's StandardIndexMaintainer.validateEntries().

type FDBRecordStoreStateCache

type FDBRecordStoreStateCache interface {
	// Get retrieves store state, using the cache if possible.
	// On cache hit, adds a read conflict on the STORE_INFO key to ensure
	// the transaction fails if concurrent modifications occur.
	// On cache miss, loads fresh state from FDB.
	Get(store *FDBRecordStore, existenceCheck StoreExistenceCheck) (*FDBRecordStoreStateCacheEntry, error)

	// Clear removes all cached entries.
	Clear()
}

FDBRecordStoreStateCache caches store state (header + index states) across transactions to avoid repeated reads of the store info key on every store open. Matches Java's FDBRecordStoreStateCache interface.

func PassThroughStoreStateCache

func PassThroughStoreStateCache() FDBRecordStoreStateCache

PassThroughStoreStateCache returns the singleton pass-through cache.

type FDBRecordStoreStateCacheEntry

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

FDBRecordStoreStateCacheEntry holds a cached snapshot of store state along with the metadata version stamp that was current when the state was loaded. Matches Java's FDBRecordStoreStateCacheEntry.

func (*FDBRecordStoreStateCacheEntry) GetMetaDataVersionStamp

func (e *FDBRecordStoreStateCacheEntry) GetMetaDataVersionStamp() []byte

GetMetaDataVersionStamp returns the metadata version stamp captured at load time.

func (*FDBRecordStoreStateCacheEntry) GetRecordStoreState

func (e *FDBRecordStoreStateCacheEntry) GetRecordStoreState() *RecordStoreState

GetRecordStoreState returns the cached store state.

type FDBRecordVersion

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

FDBRecordVersion represents a version associated with a record in the store. Matches Java's FDBRecordVersion exactly: - 12 bytes total: 10-byte global version (FDB versionstamp) + 2-byte local version - Global version: 8-byte DB commit version (big-endian) + 2-byte batch ordering - Local version: per-transaction counter (big-endian uint16)

Versions can be "complete" (global version known) or "incomplete" (pending commit). Incomplete versions have all-0xFF in the global version bytes.

func CompleteVersionFromBytes

func CompleteVersionFromBytes(b []byte) (*FDBRecordVersion, error)

CompleteVersionFromBytes parses a complete 12-byte version. Rejects versions with all-0xFF global bytes (incomplete marker). Matches Java's FDBRecordVersion.complete(byte[], boolean) constructor validation.

func FirstInDBVersion

func FirstInDBVersion(dbVersion int64) *FDBRecordVersion

FirstInDBVersion returns the first version with the given DB commit version. The batch and local portions are set to 0. Matches Java's FDBRecordVersion.firstInDBVersion().

func FirstInGlobalVersion

func FirstInGlobalVersion(globalVersion []byte) (*FDBRecordVersion, error)

FirstInGlobalVersion returns the first version with the given 10-byte global version. The local version is set to 0. Matches Java's FDBRecordVersion.firstInGlobalVersion().

func FromVersionstamp

func FromVersionstamp(vs tuple.Versionstamp) *FDBRecordVersion

FromVersionstamp creates a complete FDBRecordVersion from an FDB tuple.Versionstamp. Matches Java's FDBRecordVersion.fromVersionstamp(Versionstamp).

func IncompleteVersion

func IncompleteVersion(localVersion int) (*FDBRecordVersion, error)

IncompleteVersion creates an incomplete version with the given local version. The global version is set to all-0xFF (will be filled in at commit time).

func LastInDBVersion

func LastInDBVersion(dbVersion int64) *FDBRecordVersion

LastInDBVersion returns the last version with the given DB commit version. The batch portion is set to 0xFFFF and local to 0xFFFF. Matches Java's FDBRecordVersion.lastInDBVersion().

func LastInGlobalVersion

func LastInGlobalVersion(globalVersion []byte) (*FDBRecordVersion, error)

LastInGlobalVersion returns the last version with the given 10-byte global version. The local version is set to 0xFFFF. Matches Java's FDBRecordVersion.lastInGlobalVersion().

func MaxVersion

func MaxVersion() *FDBRecordVersion

MaxVersion returns the maximum possible complete version. Matches Java's FDBRecordVersion.MAX_VERSION:

global bytes 0-8: 0xFF, byte 9: 0xFE (0xFF...FF would mean incomplete)
local bytes 10-11: 0xFF

func MinVersion

func MinVersion() *FDBRecordVersion

MinVersion returns the minimum possible complete version (all zeros). Matches Java's FDBRecordVersion.MIN_VERSION.

func NewCompleteVersion

func NewCompleteVersion(globalVersion []byte, localVersion int) (*FDBRecordVersion, error)

NewCompleteVersion creates a complete version from 10-byte global version and local version.

func (*FDBRecordVersion) Equal

func (v *FDBRecordVersion) Equal(other *FDBRecordVersion) bool

Equal returns true if two versions are equal. Complete versions compare all 12 bytes; incomplete versions compare local version only. Matches Java's FDBRecordVersion.equals().

func (*FDBRecordVersion) GetDBVersion

func (v *FDBRecordVersion) GetDBVersion() (int64, error)

GetDBVersion returns the 8-byte FDB commit version (big-endian). Returns an error if the version is incomplete.

func (*FDBRecordVersion) GetGlobalVersion

func (v *FDBRecordVersion) GetGlobalVersion() ([]byte, error)

GetGlobalVersion returns the 10-byte global versionstamp. Returns an error if the version is incomplete.

func (*FDBRecordVersion) GetLocalVersion

func (v *FDBRecordVersion) GetLocalVersion() int

GetLocalVersion returns the 2-byte local version counter.

func (*FDBRecordVersion) IsComplete

func (v *FDBRecordVersion) IsComplete() bool

IsComplete returns true if the global version is known.

func (*FDBRecordVersion) Less

func (v *FDBRecordVersion) Less(other *FDBRecordVersion) bool

Less returns true if v sorts before other. Complete versions sort before incomplete. Among versions of the same completeness, lexicographic byte comparison of the full 12-byte raw representation. Matches Java's FDBRecordVersion.compareTo().

func (*FDBRecordVersion) Next

func (v *FDBRecordVersion) Next() (*FDBRecordVersion, error)

Next returns the version immediately after this one. For complete versions: treats all 12 bytes as big-endian unsigned integer, +1 with carry. For incomplete versions: only increments local version (last 2 bytes). Matches Java's FDBRecordVersion.next().

func (*FDBRecordVersion) Prev

func (v *FDBRecordVersion) Prev() (*FDBRecordVersion, error)

Prev returns the version immediately before this one. For complete versions: treats all 12 bytes as big-endian unsigned integer, -1 with borrow. For incomplete versions: only decrements local version (last 2 bytes). Matches Java's FDBRecordVersion.prev().

func (*FDBRecordVersion) String

func (v *FDBRecordVersion) String() string

String returns a human-readable representation matching Java's toString(). Format: "FDBRecordVersion(complete=<bool>, raw=<hex>)"

func (*FDBRecordVersion) ToBytes

func (v *FDBRecordVersion) ToBytes() []byte

ToBytes serializes the version to 12 bytes.

func (*FDBRecordVersion) ToVersionstamp

func (v *FDBRecordVersion) ToVersionstamp() (tuple.Versionstamp, error)

ToVersionstamp converts this complete version to an FDB tuple.Versionstamp. Returns an error if the version is incomplete. Matches Java's FDBRecordVersion.toVersionstamp().

func (*FDBRecordVersion) WithCommittedVersion

func (v *FDBRecordVersion) WithCommittedVersion(committedVersion []byte) (*FDBRecordVersion, error)

WithCommittedVersion completes an incomplete version using the committed versionstamp. This is called after transaction commit when the real versionstamp is known. Returns an error if the version is already complete. Matches Java's FDBRecordVersion.withCommittedVersion().

type FDBStoredRecord

type FDBStoredRecord[M proto.Message] struct {
	// PrimaryKey is the record's primary key
	PrimaryKey tuple.Tuple

	// RecordType is the type of this record
	RecordType *RecordType

	// Record is the actual record data
	Record M

	// Version is the record's version, if loaded.
	// Matches Java's FDBStoredRecord.getVersion().
	Version *FDBRecordVersion

	// Store is the record store this record belongs to.
	// Used by FunctionKeyExpression (e.g. get_versionstamp_incarnation) to access store state.
	// Matches Java's FDBRecord.getStore().
	Store *FDBRecordStore

	// Storage size information
	KeyCount  int
	KeySize   int
	ValueSize int

	// Whether the record is split across multiple keys
	Split bool
}

FDBStoredRecord represents a record that has been stored in or loaded from FDB This is generic to match Java's FDBStoredRecord<M extends Message>

func (*FDBStoredRecord[M]) HasVersion

func (r *FDBStoredRecord[M]) HasVersion() bool

HasVersion returns whether this stored record has a version. Matches Java's FDBStoredRecord.hasVersion().

type FanType

type FanType int

FanType controls how repeated (list) proto fields are handled in key expressions. Matches Java's com.apple.foundationdb.record.metadata.expressions.KeyExpression.FanType.

const (
	// FanTypeNone means the field must not be repeated. This is the default.
	FanTypeNone FanType = iota
	// FanTypeFanOut produces one tuple per repeated value — used for multi-entry indexes.
	FanTypeFanOut
	// FanTypeConcatenate puts all repeated values into a single tuple element.
	FanTypeConcatenate
)

type FieldKeyExpression

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

FieldKeyExpression extracts a single field value from a record for use as a key component. For repeated fields, use FanOut() or Concatenate() to control multi-value handling.

func (*FieldKeyExpression) ColumnSize

func (f *FieldKeyExpression) ColumnSize() int

ColumnSize returns 1 — a field expression produces a single tuple element.

func (*FieldKeyExpression) Evaluate

func (f *FieldKeyExpression) Evaluate(_ *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

Evaluate extracts the field value(s) from the message. For non-repeated fields, returns one tuple with the single value. For repeated fields with FanOut, returns one tuple per value. For repeated fields with Concatenate, returns one tuple containing a nested tuple of all values.

func (*FieldKeyExpression) EvaluateFlat

func (f *FieldKeyExpression) EvaluateFlat(record *FDBStoredRecord[proto.Message], msg proto.Message) ([]any, error)

EvaluateFlat returns the scalar value directly as a single-element []any.

func (*FieldKeyExpression) EvaluateInt64

func (f *FieldKeyExpression) EvaluateInt64(record *FDBStoredRecord[proto.Message], msg proto.Message) (int64, bool, error)

EvaluateInt64 returns the field value as int64 without boxing. Returns (0, false, nil) for nil/unset fields, (val, true, nil) for integer fields.

func (*FieldKeyExpression) EvaluateScalar

func (f *FieldKeyExpression) EvaluateScalar(record *FDBStoredRecord[proto.Message], msg proto.Message) (any, error)

EvaluateScalar returns the single scalar value directly — zero allocs for the return.

func (*FieldKeyExpression) FieldNames

func (f *FieldKeyExpression) FieldNames() []string

FieldNames returns the field name accessed by this expression

func (*FieldKeyExpression) PackDirect

PackDirect encodes the field value directly into a Packer without boxing into any. Returns false if the field is nil/unset or not a directly-packable type.

func (*FieldKeyExpression) ToKeyExpression

func (f *FieldKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes a FieldKeyExpression to proto. Matches Java's FieldKeyExpression.toKeyExpression().

type FlatEvaluator

type FlatEvaluator interface {
	EvaluateFlat(record *FDBStoredRecord[proto.Message], msg proto.Message) ([]any, error)
}

FlatEvaluator is an optional interface for KeyExpressions that can return a single tuple directly without the [][]any wrapper. Avoids 1 alloc per call.

type FormerIndex

type FormerIndex struct {
	SubspaceKey    any
	AddedVersion   int
	RemovedVersion int
	FormerName     string
}

FormerIndex tracks a deleted index for schema evolution safety. Prevents accidental reuse of an index's subspace key after deletion. Matches Java's com.apple.foundationdb.record.metadata.FormerIndex.

type FunctionEvaluator

type FunctionEvaluator func(record *FDBStoredRecord[proto.Message], msg proto.Message, arguments [][]any) ([][]any, error)

FunctionEvaluator evaluates a named function on a record. Arguments are the pre-evaluated argument tuples from the arguments expression.

type FunctionKeyExpression

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

FunctionKeyExpression evaluates a named function on records to produce index key values. The function is resolved from the global registry by name. Matches Java's FunctionKeyExpression abstract class.

func FunctionExpr

func FunctionExpr(name string, arguments KeyExpression) *FunctionKeyExpression

FunctionExpr creates a FunctionKeyExpression with the given name and arguments. The function must be registered in the global registry before evaluation. Matches Java's FunctionKeyExpression.create(name, arguments).

func OrderFuncExpr

func OrderFuncExpr(direction string, arguments KeyExpression) *FunctionKeyExpression

OrderFuncExpr creates a FunctionKeyExpression for ordering with the given direction name and arguments. Convenience wrapper matching Java's OrderFunctionKeyExpression constructor.

func (*FunctionKeyExpression) Arguments

func (f *FunctionKeyExpression) Arguments() KeyExpression

Arguments returns the arguments key expression.

func (*FunctionKeyExpression) ColumnSize

func (f *FunctionKeyExpression) ColumnSize() int

ColumnSize returns 1 — a function expression produces a single tuple element.

func (*FunctionKeyExpression) Evaluate

func (f *FunctionKeyExpression) Evaluate(record *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

Evaluate resolves the named function from the registry, evaluates arguments, and applies the function. Matches Java's FunctionKeyExpression.evaluateMessage().

func (*FunctionKeyExpression) FieldNames

func (f *FunctionKeyExpression) FieldNames() []string

FieldNames returns field names from the arguments expression.

func (*FunctionKeyExpression) Name

func (f *FunctionKeyExpression) Name() string

Name returns the function name.

func (*FunctionKeyExpression) ToKeyExpression

func (f *FunctionKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes a FunctionKeyExpression to proto. Matches Java's FunctionKeyExpression.toKeyExpression().

type GroupingKeyExpression

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

GroupingKeyExpression wraps a key expression and divides its columns into "grouping" (leading) and "grouped" (trailing) parts. The grouping columns form the GROUP BY key, and the grouped columns are the aggregated values. Matches Java's com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression.

func GroupAll

func GroupAll(expr KeyExpression) *GroupingKeyExpression

GroupAll creates a GroupingKeyExpression where all columns are "grouping" and there are no aggregated columns. Used for COUNT indexes where the entire expression forms the GROUP BY key. Example: GroupAll(Field("price")) → count grouped by price. Matches Java's new GroupingKeyExpression(expr, 0).

func GroupBy

func GroupBy(grouped KeyExpression, groupBy ...KeyExpression) *GroupingKeyExpression

GroupBy creates a GroupingKeyExpression that groups by the given expressions and treats the receiver as the aggregated value. Example: Field("score").GroupBy(Field("game_id")) →

wholeKey = Concat(game_id, score), groupedCount = 1

Matches Java's KeyExpression.groupBy().

func Ungrouped

func Ungrouped(expr KeyExpression) *GroupingKeyExpression

Ungrouped creates a GroupingKeyExpression where all columns are "grouped" (aggregated) and there are no grouping columns. Used for ungrouped counts. Example: Ungrouped(EmptyKey()) → count all records with no grouping. Matches Java's KeyExpression.ungrouped().

func (*GroupingKeyExpression) ColumnSize

func (g *GroupingKeyExpression) ColumnSize() int

ColumnSize delegates to the whole key expression's column size.

func (*GroupingKeyExpression) Evaluate

func (g *GroupingKeyExpression) Evaluate(record *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

Evaluate delegates to the whole key expression. The grouping/grouped split is metadata, not evaluation logic.

func (*GroupingKeyExpression) EvaluateFlat

func (g *GroupingKeyExpression) EvaluateFlat(record *FDBStoredRecord[proto.Message], msg proto.Message) ([]any, error)

EvaluateFlat delegates to the whole key's EvaluateFlat if available.

func (*GroupingKeyExpression) FieldNames

func (g *GroupingKeyExpression) FieldNames() []string

FieldNames returns field names from the whole key.

func (*GroupingKeyExpression) GetGroupedCount

func (g *GroupingKeyExpression) GetGroupedCount() int

GetGroupedCount returns the number of trailing "grouped" (aggregated) columns.

func (*GroupingKeyExpression) GetGroupingCount

func (g *GroupingKeyExpression) GetGroupingCount() int

GetGroupingCount returns the number of leading "grouping" (GROUP BY) columns.

func (*GroupingKeyExpression) ToKeyExpression

func (g *GroupingKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes GroupingKeyExpression to proto. Matches Java's GroupingKeyExpression.toKeyExpression().

type HNSWConfig

type HNSWConfig struct {
	NumDimensions         int
	M                     int             // Connectivity factor (default 16)
	MMax                  int             // Max connections for non-zero layers (default 16 — Java DEFAULT_M_MAX, a constant, NOT derived from M; setting M > 16 requires setting MMax too, like Java)
	MMax0                 int             // Max connections for layer 0 (default 32 — Java DEFAULT_M_MAX_0, a constant, NOT derived from M)
	EfConstruction        int             // Insertion search factor (default 200)
	Metric                VectorMetric    // Distance metric
	ExtendCandidates      bool            // Extend candidate set with 2nd-degree neighbors (default false)
	KeepPrunedConnections bool            // Retain pruned candidates to fill up to M (default false)
	EfRepair              int             // Delete-repair beam width; Java requires [m, 400] (default 64; 0 means "use default")
	UseInlining           bool            // Use inlining storage for layers > 0 (default false)
	Quantizer             VectorQuantizer // Optional quantizer (nil = raw float64 storage)

	// RaBitQ centroid-bootstrap stats (Java Config). When RaBitQ is enabled and no centroid
	// is yet established, inserts sample vectors into the SAMPLES subspace, periodically roll
	// them up, and once StatsThreshold vectors have accumulated, establish the rotated centroid.
	SampleVectorStatsProbability float64 // prob of sampling each inserted vector (default 0.5)
	MaintainStatsProbability     float64 // prob of rolling up samples on an insert (default 0.05)
	StatsThreshold               int     // accumulated count needed to establish the centroid (default 1000)

	// Concurrency limits — Java uses these to limit async pipeline parallelism.
	// Go's synchronous FDB model doesn't use these for concurrency control, but
	// we store and round-trip them so Java-written configs are preserved.
	// Matches Java's Config.maxNumConcurrentNodeFetches etc.
	MaxNumConcurrentNodeFetches         int // (0, 64], default 16 — node fetch parallelism in Java
	MaxNumConcurrentNeighborhoodFetches int // (0, 20], default 10 — neighborhood fetch parallelism in Java
	MaxNumConcurrentDeleteFromLayer     int // (0, 10], default 2  — layer deletion parallelism in Java
}

HNSWConfig configures an HNSW graph. Matches Java's com.apple.foundationdb.async.hnsw.Config.

func DefaultHNSWConfig

func DefaultHNSWConfig(numDimensions int) HNSWConfig

DefaultHNSWConfig returns a default HNSW configuration.

type HNSWStats

type HNSWStats struct {
	FDBGets       atomic.Int64 // individual Get() calls (point reads)
	FDBBatchGets  atomic.Int64 // batched Get() calls (pipelined, count as 1 RT)
	FDBRangeReads atomic.Int64 // GetRange() calls
	CacheHits     atomic.Int64 // reads served from in-tx cache
}

HNSWStats tracks I/O counters for a single HNSW operation. Attach to a context via WithHNSWStats and retrieve via GetHNSWStats. Zero cost when not attached — all tracking is behind a nil check.

func GetHNSWStats

func GetHNSWStats(ctx context.Context) *HNSWStats

GetHNSWStats retrieves HNSWStats from a context, or nil if not tracking.

func WithHNSWStats

func WithHNSWStats(ctx context.Context) (context.Context, *HNSWStats)

WithHNSWStats attaches an HNSWStats to the context for I/O tracking.

type Index

type Index struct {
	Name           string
	Type           string
	RootExpression KeyExpression

	Options             map[string]string
	AddedVersion        int
	LastModifiedVersion int

	// Predicate filters which records are included in this index.
	// If nil, all records are indexed. If set, only records where
	// Predicate returns true are indexed (sparse/filtered index).
	Predicate IndexPredicate
	// contains filtered or unexported fields
}

Index represents a secondary index definition. Matches Java's com.apple.foundationdb.record.metadata.Index.

func NewBitmapValueIndex

func NewBitmapValueIndex(name string, rootExpression KeyExpression) *Index

NewBitmapValueIndex creates a BITMAP_VALUE index with the given name and root key expression. BITMAP_VALUE indexes store one bit per record in fixed-size bitmaps, using atomic BIT_OR/BIT_AND operations for set/clear. The position field is the last grouped column. Matches Java's new Index(name, rootExpression, IndexTypes.BITMAP_VALUE).

func NewCountIndex

func NewCountIndex(name string, rootExpression KeyExpression) *Index

NewCountIndex creates a COUNT index with the given name and root key expression. COUNT indexes use FDB atomic ADD to maintain counts per grouping key. Matches Java's new Index(name, rootExpression, IndexTypes.COUNT).

func NewCountNotNullIndex

func NewCountNotNullIndex(name string, rootExpression KeyExpression) *Index

NewCountNotNullIndex creates a COUNT_NOT_NULL index with the given name and root key expression. Like COUNT, but skips entries where the key contains a null value (nil element). Matches Java's new Index(name, rootExpression, IndexTypes.COUNT_NOT_NULL).

func NewCountUpdatesIndex

func NewCountUpdatesIndex(name string, rootExpression KeyExpression) *Index

NewCountUpdatesIndex creates a COUNT_UPDATES index with the given name and root key expression. Like COUNT, but deletes are no-ops (count never decrements) and updates always re-count (skipUpdateForUnchangedKeys = false). Tracks total insert+update events. Matches Java's new Index(name, rootExpression, IndexTypes.COUNT_UPDATES).

func NewIndex

func NewIndex(name string, rootExpression KeyExpression) *Index

NewIndex creates a VALUE index with the given name and root key expression. Matches Java's new Index(name, rootExpression) which defaults to IndexTypes.VALUE.

func NewMaxEverLongIndex

func NewMaxEverLongIndex(name string, rootExpression KeyExpression) *Index

NewMaxEverLongIndex creates a MAX_EVER_LONG index with the given name and root key expression. MAX_EVER_LONG indexes use FDB atomic MAX to track the maximum value seen per grouping key. Values must be non-negative (unsigned comparison). Deletes are no-ops (_EVER = irreversible). Matches Java's new Index(name, rootExpression, IndexTypes.MAX_EVER_LONG).

func NewMaxEverTupleIndex

func NewMaxEverTupleIndex(name string, rootExpression KeyExpression) *Index

NewMaxEverTupleIndex creates a MAX_EVER_TUPLE index with the given name and root key expression. MAX_EVER_TUPLE indexes use FDB atomic BYTE_MAX to track the maximum tuple-packed value per grouping key. Unlike MAX_EVER_LONG, accepts any tuple-encodable type and compares via byte ordering. Deletes are no-ops (_EVER = irreversible). Idempotent. Matches Java's new Index(name, rootExpression, IndexTypes.MAX_EVER_TUPLE).

func NewMaxEverVersionIndex

func NewMaxEverVersionIndex(name string, rootExpression KeyExpression) *Index

NewMaxEverVersionIndex creates a MAX_EVER_VERSION index that tracks the maximum version ever written per grouping key. The root expression must be a GroupingKeyExpression with exactly 1 VersionKeyExpression in the grouped (aggregated) portion. Matches Java's new Index(name, rootExpression, IndexTypes.MAX_EVER_VERSION).

func NewMinEverLongIndex

func NewMinEverLongIndex(name string, rootExpression KeyExpression) *Index

NewMinEverLongIndex creates a MIN_EVER_LONG index with the given name and root key expression. MIN_EVER_LONG indexes use FDB atomic MIN to track the minimum value seen per grouping key. Values must be non-negative (unsigned comparison). Deletes are no-ops (_EVER = irreversible). Matches Java's new Index(name, rootExpression, IndexTypes.MIN_EVER_LONG).

func NewMinEverTupleIndex

func NewMinEverTupleIndex(name string, rootExpression KeyExpression) *Index

NewMinEverTupleIndex creates a MIN_EVER_TUPLE index with the given name and root key expression. MIN_EVER_TUPLE indexes use FDB atomic BYTE_MIN to track the minimum tuple-packed value per grouping key. Unlike MIN_EVER_LONG, accepts any tuple-encodable type and compares via byte ordering. Deletes are no-ops (_EVER = irreversible). Idempotent. Matches Java's new Index(name, rootExpression, IndexTypes.MIN_EVER_TUPLE).

func NewMultidimensionalIndex

func NewMultidimensionalIndex(name string, rootExpression KeyExpression) *Index

NewMultidimensionalIndex creates a MULTIDIMENSIONAL index backed by a Hilbert R-tree. The root expression must be a DimensionsKeyExpression that specifies prefix, dimensions, and suffix. Matches Java's new Index(name, rootExpression, IndexTypes.MULTIDIMENSIONAL).

func NewPermutedMaxIndex

func NewPermutedMaxIndex(name string, rootExpression KeyExpression, permutedSize int) *Index

NewPermutedMaxIndex creates a PERMUTED_MAX index with the given name, root key expression, and permuted size. The permuted size specifies how many trailing grouping columns are permuted to after the value in the secondary subspace, enabling value-ordered scans. Matches Java's new Index(name, rootExpression, IndexTypes.PERMUTED_MAX) with PERMUTED_SIZE_OPTION.

func NewPermutedMinIndex

func NewPermutedMinIndex(name string, rootExpression KeyExpression, permutedSize int) *Index

NewPermutedMinIndex creates a PERMUTED_MIN index with the given name, root key expression, and permuted size. The permuted size specifies how many trailing grouping columns are permuted to after the value in the secondary subspace, enabling value-ordered scans. Matches Java's new Index(name, rootExpression, IndexTypes.PERMUTED_MIN) with PERMUTED_SIZE_OPTION.

func NewRankIndex

func NewRankIndex(name string, rootExpression KeyExpression) *Index

NewRankIndex creates a RANK index with the given name and root key expression. RANK indexes maintain a B-tree (like VALUE) plus a skip-list ranked set per group for O(log n) rank/select queries. Matches Java's new Index(name, rootExpression, IndexTypes.RANK).

func NewSumIndex

func NewSumIndex(name string, rootExpression KeyExpression) *Index

NewSumIndex creates a SUM index with the given name and root key expression. SUM indexes use FDB atomic ADD to maintain running sums per grouping key. The expression must include at least one grouped (aggregated) column. Matches Java's new Index(name, rootExpression, IndexTypes.SUM).

func NewTextIndex

func NewTextIndex(name string, rootExpression KeyExpression) *Index

NewTextIndex creates a TEXT index with the given name and root key expression. TEXT indexes tokenize string fields and store per-token position lists in a BunchedMap. Matches Java's new Index(name, rootExpression, IndexTypes.TEXT).

func NewTimeWindowLeaderboardIndex

func NewTimeWindowLeaderboardIndex(name string, rootExpression KeyExpression) *Index

NewTimeWindowLeaderboardIndex creates a TIME_WINDOW_LEADERBOARD index. TIME_WINDOW_LEADERBOARD indexes maintain multiple ranked sets, one per time window, enabling time-windowed leaderboard queries. Matches Java's new Index(name, rootExpression, IndexTypes.TIME_WINDOW_LEADERBOARD).

func NewVectorIndex

func NewVectorIndex(name string, rootExpression KeyExpression, numDimensions int) *Index

NewVectorIndex creates a VECTOR index backed by an HNSW graph. The root expression identifies the vector field to index. numDimensions specifies the vector dimensionality. Supports EUCLIDEAN, COSINE, and INNER_PRODUCT metrics. Matches Java's new Index(name, rootExpression, IndexTypes.VECTOR).

func NewVersionIndex

func NewVersionIndex(name string, rootExpression KeyExpression) *Index

NewVersionIndex creates a VERSION index with the given name and root key expression. VERSION indexes store the record's commit version in the index key for version-ordered queries. The root expression should include a VersionKeyExpression (typically via Concat with other fields). Matches Java's new Index(name, rootExpression, IndexTypes.VERSION).

func (*Index) GetBooleanOption

func (idx *Index) GetBooleanOption(key string, defaultVal bool) bool

GetBooleanOption returns the boolean value of an index option. Returns the default value if the option is not set. Matches Java's Index.getBooleanOption(String, boolean).

func (*Index) GetPredicateProto

func (idx *Index) GetPredicateProto() *gen.Predicate

GetPredicateProto returns the proto representation of the predicate, if any. Returns nil for programmatic Go predicates set via SetPredicate().

func (*Index) GetReplacedByIndexNames

func (idx *Index) GetReplacedByIndexNames() []string

GetReplacedByIndexNames returns the names of indexes that replace this one. Options with keys starting with "replacedBy" (e.g. "replacedBy", "replacedBy_0") have their values as replacement index names. Matches Java's Index.getReplacedByIndexNames().

func (*Index) HasPrimaryKeyComponentPositions

func (idx *Index) HasPrimaryKeyComponentPositions() bool

HasPrimaryKeyComponentPositions returns true if the index has computed PK component positions. Matches Java's Index.hasPrimaryKeyComponentPositions().

func (*Index) IsClearWhenZero

func (idx *Index) IsClearWhenZero() bool

IsClearWhenZero returns whether this index should clear entries when values reach zero. When true, atomic ADD mutations are followed by CompareAndClear(zero) to remove stale zero-value entries. Applies to COUNT, COUNT_NOT_NULL, and SUM indexes. Matches Java's IndexOptions.CLEAR_WHEN_ZERO.

func (*Index) IsUnique

func (idx *Index) IsUnique() bool

IsUnique returns whether this index enforces a uniqueness constraint. Matches Java's Index.isUnique() which checks IndexOptions.UNIQUE_OPTION.

func (*Index) PrimaryKeyComponentPositions

func (idx *Index) PrimaryKeyComponentPositions() []int

PrimaryKeyComponentPositions returns the overlap mapping between index key and primary key. nil means no overlap was computed. Matches Java's Index.getPrimaryKeyComponentPositions().

func (*Index) SetClearWhenZero

func (idx *Index) SetClearWhenZero(clear bool) *Index

SetClearWhenZero enables or disables the clear-when-zero behavior. Matches Java's IndexOptions.CLEAR_WHEN_ZERO.

func (*Index) SetPredicate

func (idx *Index) SetPredicate(p IndexPredicate) *Index

SetPredicate sets a filter predicate for sparse/filtered indexes. Only records where the predicate returns true will have index entries. Note: programmatic Go predicates cannot be serialized to proto. Use SetPredicateProto for predicates that must survive metadata round-tripping.

func (*Index) SetPredicateProto

func (idx *Index) SetPredicateProto(p *gen.Predicate) error

SetPredicateProto sets a predicate from a proto message. This both stores the proto for round-tripping and builds an evaluator function.

func (*Index) SetSubspaceKey

func (idx *Index) SetSubspaceKey(key any) *Index

SetSubspaceKey overrides the default subspace key (index name). Matches Java's Index.setSubspaceKey().

func (*Index) SetUnique

func (idx *Index) SetUnique() *Index

SetUnique marks this index as enforcing uniqueness.

func (*Index) SubspaceTupleKey

func (idx *Index) SubspaceTupleKey() any

SubspaceTupleKey returns the key used to identify this index's subspace within the IndexKey (2) subspace. Defaults to the index name. Matches Java's Index.getSubspaceTupleKey().

func (*Index) TrimPrimaryKey

func (idx *Index) TrimPrimaryKey(primaryKey tuple.Tuple) (tuple.Tuple, error)

trimPrimaryKey removes PK components that already appear in the index key. Returns the remaining PK components that need to be appended to the index entry. Returns an error if primaryKeyComponentPositions references an index beyond the primary key length. Matches Java's Index.TrimPrimaryKey().

type IndexAggregateFunction

type IndexAggregateFunction struct {
	Name    string        // Function name (e.g. "count", "sum", "min_ever")
	Operand KeyExpression // The operand (typically a GroupingKeyExpression)
	Index   string        // Optional: explicit index name. Empty = auto-select.
}

IndexAggregateFunction specifies an aggregate computation to evaluate via an index. Matches Java's com.apple.foundationdb.record.metadata.IndexAggregateFunction.

func NewCountAggregateFunction

func NewCountAggregateFunction(operand KeyExpression) *IndexAggregateFunction

NewCountAggregateFunction creates a COUNT aggregate function. Matches Java's IndexAggregateFunction(FunctionNames.COUNT, operand).

func NewMaxAggregateFunction

func NewMaxAggregateFunction(operand KeyExpression) *IndexAggregateFunction

NewMaxAggregateFunction creates a MAX aggregate function (via VALUE index).

func NewMaxEverAggregateFunction

func NewMaxEverAggregateFunction(operand KeyExpression) *IndexAggregateFunction

NewMaxEverAggregateFunction creates a MAX_EVER aggregate function.

func NewMinAggregateFunction

func NewMinAggregateFunction(operand KeyExpression) *IndexAggregateFunction

NewMinAggregateFunction creates a MIN aggregate function (via VALUE index).

func NewMinEverAggregateFunction

func NewMinEverAggregateFunction(operand KeyExpression) *IndexAggregateFunction

NewMinEverAggregateFunction creates a MIN_EVER aggregate function.

func NewSumAggregateFunction

func NewSumAggregateFunction(operand KeyExpression) *IndexAggregateFunction

NewSumAggregateFunction creates a SUM aggregate function.

type IndexBuildState

type IndexBuildState struct {
	State          IndexState
	RecordsScanned *int64 // nil if not WRITE_ONLY or not tracked
	RecordsInTotal *int64 // nil if no COUNT index available
}

IndexBuildState reports the current state of an index build. Matches Java's com.apple.foundationdb.record.provider.foundationdb.IndexBuildState.

func LoadIndexBuildState

func LoadIndexBuildState(store *FDBRecordStore, index *Index) (*IndexBuildState, error)

LoadIndexBuildState loads the build state for an index within an open store. Matches Java's IndexBuildState.loadIndexBuildStateAsync().

type IndexEntry

type IndexEntry struct {
	Index *Index
	Key   tuple.Tuple // Full key (indexed values + primary key components)
	Value tuple.Tuple // Value tuple (empty for VALUE indexes)
	// contains filtered or unexported fields
}

IndexEntry represents a single entry from an index scan. Matches Java's com.apple.foundationdb.record.IndexEntry.

func (*IndexEntry) IndexValues

func (e *IndexEntry) IndexValues() tuple.Tuple

IndexValues extracts the indexed values portion from the entry key. Returns the prefix of Key up to the index expression's column count.

func (*IndexEntry) PrimaryKey

func (e *IndexEntry) PrimaryKey() tuple.Tuple

PrimaryKey extracts the primary key portion from the index entry key. When the index has primaryKeyComponentPositions, some PK components are pulled from the index key portion (deduplicated) and the rest from the appended tail. Matches Java's IndexEntry.getPrimaryKey() → Index.getEntryPrimaryKey().

type IndexKeySizeError

type IndexKeySizeError struct {
	IndexName  string
	PrimaryKey tuple.Tuple
	KeySize    int
	Limit      int
}

IndexKeySizeError indicates an index entry key exceeds the FDB key size limit. Matches Java's FDBExceptions.FDBStoreKeySizeException.

func (*IndexKeySizeError) Error

func (e *IndexKeySizeError) Error() string

type IndexMaintainer

type IndexMaintainer interface {
	// Update updates the index for a record change.
	// oldRecord is nil for inserts, newRecord is nil for deletes.
	Update(oldRecord, newRecord *FDBStoredRecord[proto.Message]) error

	// UpdateWhileWriteOnly updates the index during WRITE_ONLY state (index being built).
	// For idempotent indexes (VALUE), this is a pass-through to Update().
	// For non-idempotent indexes, checks if the record's PK is in the already-built range.
	// Matches Java's standardIndexMaintainer.updateWhileWriteOnly().
	UpdateWhileWriteOnly(oldRecord, newRecord *FDBStoredRecord[proto.Message]) error

	// Scan scans the index within the given tuple range.
	// Matches Java's IndexMaintainer.scan().
	Scan(scanRange TupleRange, continuation []byte, scanProperties ScanProperties) RecordCursor[*IndexEntry]

	// DeleteWhere clears all index entries whose key starts with the given prefix.
	// Uses FDB range clears — no scanning. Called by DeleteRecordsWhere.
	// Matches Java's IndexMaintainer.deleteWhere().
	DeleteWhere(prefix tuple.Tuple) error
}

IndexMaintainer handles index updates and scanning. Matches Java's com.apple.foundationdb.record.provider.foundationdb.IndexMaintainer.

type IndexNotBuiltError

type IndexNotBuiltError struct {
	IndexName string
}

IndexNotBuiltError is returned when trying to mark an index as readable but it has unbuilt ranges remaining in its range set.

func (*IndexNotBuiltError) Error

func (e *IndexNotBuiltError) Error() string

type IndexNotFoundError

type IndexNotFoundError struct {
	IndexName string
}

IndexNotFoundError is returned when an index name is not found in the metadata. Matches Java's MetaDataException for missing indexes.

func (*IndexNotFoundError) Error

func (e *IndexNotFoundError) Error() string

type IndexNotReadableError

type IndexNotReadableError struct {
	IndexName    string
	CurrentState IndexState
}

IndexNotReadableError is returned when trying to scan an index that is not in a readable state. Matches Java's com.apple.foundationdb.record.ScanNonReadableIndexException.

func (*IndexNotReadableError) Error

func (e *IndexNotReadableError) Error() string

type IndexPredicate

type IndexPredicate func(msg proto.Message) bool

IndexPredicate is a function that determines whether a record should be indexed. Return true to include the record in the index, false to skip it. Matches Java's Index predicate concept for sparse/filtered indexes.

type IndexRebuildPolicy

type IndexRebuildPolicy func(index *Index, recordCount int64, indexOnNewRecordTypes bool) IndexState

IndexRebuildPolicy determines what state a new/changed index should be put in when the store is opened with updated metadata. Matches Java's FDBRecordStoreBase.UserVersionChecker.needRebuildIndex().

type IndexRecordFunction

type IndexRecordFunction struct {
	Name    string        // Function name (e.g. "rank")
	Operand KeyExpression // The operand (typically a GroupingKeyExpression)
	Index   string        // Optional: explicit index name. Empty = auto-select.

	// TimeWindow specifies the leaderboard time window for TIME_WINDOW_RANK and
	// TIME_WINDOW_RANK_AND_ENTRY functions. Nil for plain RANK (uses all-time).
	// Matches Java's TimeWindowRecordFunction.timeWindow (TimeWindowForFunction).
	TimeWindow *TimeWindowForFunction
}

IndexRecordFunction specifies a function to evaluate on a record using an index. Matches Java's com.apple.foundationdb.record.metadata.IndexRecordFunction.

type IndexScanType

type IndexScanType string

IndexScanType identifies the type of index scan. Matches Java's com.apple.foundationdb.record.IndexScanType.

const (
	// IndexScanByValue scans a VALUE index by its indexed values.
	IndexScanByValue IndexScanType = "BY_VALUE"
	// IndexScanByRank scans a RANK index by rank position.
	// The range bounds contain [group..., rank] where rank is an int64.
	// Matches Java's IndexScanType.BY_RANK.
	IndexScanByRank IndexScanType = "BY_RANK"

	// IndexScanByTextToken scans a TEXT index by text token.
	// Matches Java's IndexScanType.BY_TEXT_TOKEN.
	IndexScanByTextToken IndexScanType = "BY_TEXT_TOKEN"

	// IndexScanByGroup scans a PERMUTED_MIN/MAX index by group in the
	// secondary (permuted) subspace. Returns one entry per group with the
	// extremum value, ordered by [groupPrefix, value, groupSuffix].
	// Matches Java's IndexScanType.BY_GROUP.
	IndexScanByGroup IndexScanType = "BY_GROUP"

	// IndexScanByTimeWindow scans a TIME_WINDOW_LEADERBOARD index within a
	// specific time window. The scan range contains score bounds; the
	// leaderboard type and timestamp are provided via TimeWindowScanRange.
	// Matches Java's IndexScanType.BY_TIME_WINDOW.
	IndexScanByTimeWindow IndexScanType = "BY_TIME_WINDOW"

	// IndexScanByDistance scans a VECTOR index by distance to a query vector.
	// Returns results sorted by distance (closest first) as a kNN search.
	// Must be used with ScanVectorIndex which provides VectorScanBounds.
	// Matches Java's IndexScanType.BY_DISTANCE.
	IndexScanByDistance IndexScanType = "BY_DISTANCE"

	// IndexScanByDistanceOrderedStream is the RFC-156 Phase C VBASE distance-
	// ordered STREAMING scan: a demand-driven cursor that widens its scanned
	// horizon in batches as the consumer (Filter → Limit) pulls, bounded by a
	// budget cap (honest ScanLimitReached truncation, never a silent < k). Go-only
	// read-side extension; no wire-format change.
	IndexScanByDistanceOrderedStream IndexScanType = "BY_DISTANCE_ORDERED_STREAM"
)

type IndexState

type IndexState int

IndexState represents the state of a secondary index. Matches Java's com.apple.foundationdb.record.IndexState.

const (
	// IndexStateReadable means the index is fully built and can be read and written.
	IndexStateReadable IndexState = 0
	// IndexStateWriteOnly means the index is being built. Written to on record changes
	// but not yet safe for queries.
	IndexStateWriteOnly IndexState = 1
	// IndexStateDisabled means the index is not maintained or readable.
	IndexStateDisabled IndexState = 2
	// IndexStateReadableUniquePending means the unique index is fully indexed but may
	// have duplicate entries. Safe to query if uniqueness is not assumed.
	IndexStateReadableUniquePending IndexState = 3
)

func AlwaysRebuildPolicy

func AlwaysRebuildPolicy(_ *Index, _ int64, _ bool) IndexState

AlwaysRebuildPolicy always rebuilds indexes inline. Matches Java's ALWAYS_READABLE_CHECKER behavior.

func DefaultIndexRebuildPolicy

func DefaultIndexRebuildPolicy(index *Index, recordCount int64, indexOnNewRecordTypes bool) IndexState

DefaultIndexRebuildPolicy matches Java's default behavior: inline rebuild (READABLE) for stores with ≤200 records or indexes on new record types, DISABLED otherwise (requires OnlineIndexer). Java constant: FDBRecordStoreBase.MAX_RECORDS_FOR_REBUILD = 200.

func WriteOnlyIfTooLargePolicy

func WriteOnlyIfTooLargePolicy(index *Index, recordCount int64, indexOnNewRecordTypes bool) IndexState

WriteOnlyIfTooLargePolicy returns READABLE for small stores (inline rebuild) and WRITE_ONLY for larger stores. WRITE_ONLY is the production-safe choice: new writes maintain the index immediately, and the operator invokes OnlineIndexer to backfill historical data. This avoids both:

  • READABLE: times out on large stores (single-transaction rebuild)
  • DISABLED: index is completely ignored, new writes don't maintain it

Threshold matches Java's MAX_RECORDS_FOR_REBUILD = 200.

func (IndexState) IsDisabled

func (s IndexState) IsDisabled() bool

IsDisabled returns true if this index is in DISABLED state.

func (IndexState) IsScannable

func (s IndexState) IsScannable() bool

IsScannable returns true if this state allows index scans. Matches Java's IndexState.isScannable() — READABLE or READABLE_UNIQUE_PENDING.

func (IndexState) IsWriteOnly

func (s IndexState) IsWriteOnly() bool

IsWriteOnly returns true if this index is in WRITE_ONLY state.

func (IndexState) String

func (s IndexState) String() string

type IndexValidationEntry

type IndexValidationEntry struct {
	IndexKey   tuple.Tuple
	PrimaryKey tuple.Tuple
}

IndexValidationEntry represents a single missing or orphaned index entry.

type IndexValidationResult

type IndexValidationResult struct {
	// MissingEntries are index entries that should exist (based on records) but don't.
	MissingEntries []IndexValidationEntry
	// OrphanedEntries are index entries that exist but have no corresponding record.
	OrphanedEntries []IndexValidationEntry
	// TotalRecordsScanned is the number of records checked.
	TotalRecordsScanned int
	// TotalEntriesScanned is the number of index entries checked.
	TotalEntriesScanned int
}

IndexValidationResult contains the results of an index validation.

func (*IndexValidationResult) IsValid

func (r *IndexValidationResult) IsValid() bool

IsValid returns true if no discrepancies were found.

type IndexValueSizeError

type IndexValueSizeError struct {
	IndexName  string
	PrimaryKey tuple.Tuple
	ValueSize  int
	Limit      int
}

IndexValueSizeError indicates an index entry value exceeds the FDB value size limit. Matches Java's FDBExceptions.FDBStoreValueSizeException.

func (*IndexValueSizeError) Error

func (e *IndexValueSizeError) Error() string

type IndexingHeartbeat

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

IndexingHeartbeat manages liveness heartbeats for concurrent index building. Each indexer process writes a heartbeat at [9, indexSubspaceKey, 7, uuid] so that other processes can detect stale/crashed builders.

In non-mutual (exclusive) mode, an active heartbeat from another process prevents this indexer from starting. In mutual mode, heartbeats are written but not checked (concurrent building is allowed).

Matches Java's IndexingHeartbeat.

func NewIndexingHeartbeat

func NewIndexingHeartbeat(info string, leaseLengthMs int64, allowMutual bool) *IndexingHeartbeat

NewIndexingHeartbeat creates a heartbeat manager for an indexer. leaseLengthMs is how long a heartbeat remains valid before being considered stale.

func (*IndexingHeartbeat) CheckAndUpdate

func (h *IndexingHeartbeat) CheckAndUpdate(tx fdb.WritableTransaction, storeSubspace subspace.Subspace, index *Index) error

CheckAndUpdate checks for conflicting heartbeats and updates this indexer's heartbeat.

In non-mutual mode: scans all heartbeats for this index. If any active (non-stale) heartbeat from a different indexer exists, returns a SynchronizedSessionLockedError. Stale heartbeats (older than leaseLengthMs) are ignored — the process is presumed dead.

In mutual mode: skips the check entirely and just updates.

Called once per buildRange transaction to maintain liveness. Matches Java's IndexingHeartbeat.checkAndUpdateHeartbeat().

func (*IndexingHeartbeat) Cleanup

func (h *IndexingHeartbeat) Cleanup(tx fdb.WritableTransaction, storeSubspace subspace.Subspace, index *Index)

Cleanup removes this indexer's heartbeat. Called when the build completes or is explicitly cancelled. Matches Java's IndexingHeartbeat.removeHeartbeat().

type IndexingPolicy

type IndexingPolicy struct {
	// ForceStampOverwrite forces writing the stamp without conflict checks on
	// fresh (non-continued) builds, or allows overwriting on continued builds
	// when no records have been scanned. Used internally during rebuild.
	ForceStampOverwrite bool

	// AllowUnblock permits unblocking a blocked stamp during resume.
	AllowUnblock bool

	// AllowUnblockID restricts unblocking to stamps with a matching blockID.
	// Empty string means any blockID is accepted (when AllowUnblock is true).
	AllowUnblockID string

	// AllowedTakeovers is the set of allowed build method conversions.
	AllowedTakeovers map[TakeoverType]bool
}

IndexingPolicy configures how the OnlineIndexer handles stamp conflicts, blocked stamps, and build method conversions. Matches Java's OnlineIndexer.IndexingPolicy.

func (*IndexingPolicy) ShouldAllowTypeConversionContinue

func (p *IndexingPolicy) ShouldAllowTypeConversionContinue(newStamp, savedStamp *gen.IndexBuildIndexingStamp) bool

ShouldAllowTypeConversionContinue returns true if switching from savedStamp's method to newStamp's method is permitted by the policy. Matches Java's IndexingPolicy.shouldAllowTypeConversionContinue().

func (*IndexingPolicy) ShouldAllowUnblock

func (p *IndexingPolicy) ShouldAllowUnblock(stampBlockID string) bool

ShouldAllowUnblock returns true if the policy allows unblocking a stamp with the given blockID. Matches Java's IndexingPolicy.shouldAllowUnblock().

type IndexingRangeSet

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

IndexingRangeSet wraps a RangeSet scoped to a specific index's build progress. Lives at store subspace [IndexRangeSpaceKey (6), indexSubspaceKey]. Wire-compatible with Java's IndexingRangeSet.

func NewIndexingRangeSet

func NewIndexingRangeSet(storeSubspace subspace.Subspace, index *Index) *IndexingRangeSet

NewIndexingRangeSet creates an IndexingRangeSet for the given index within the store's subspace. Matches Java's IndexingRangeSet.forIndexBuild(store, index).

func (*IndexingRangeSet) Clear

func (irs *IndexingRangeSet) Clear(tr fdb.WritableTransaction)

Clear removes all range tracking data.

func (*IndexingRangeSet) ContainsKey

func (irs *IndexingRangeSet) ContainsKey(tr fdb.WritableTransaction, key []byte) (bool, error)

ContainsKey checks if a primary key (tuple-packed bytes) is in the built range.

func (*IndexingRangeSet) FirstMissingRange

func (irs *IndexingRangeSet) FirstMissingRange(tr fdb.WritableTransaction) (*RangeSetRange, error)

FirstMissingRange returns the first gap in the range set, or nil if complete.

func (*IndexingRangeSet) InsertRange

func (irs *IndexingRangeSet) InsertRange(tr fdb.WritableTransaction, begin, end []byte, requireEmpty bool) (bool, error)

InsertRange marks a range as built. Returns true if the database was modified.

func (*IndexingRangeSet) IsComplete

func (irs *IndexingRangeSet) IsComplete(tr fdb.WritableTransaction) (bool, error)

IsComplete returns true if all ranges have been built.

func (*IndexingRangeSet) ListMissingRanges

func (irs *IndexingRangeSet) ListMissingRanges(tr fdb.WritableTransaction) ([]RangeSetRange, error)

ListMissingRanges returns all gaps in the range set.

func (*IndexingRangeSet) ListMissingRangesInBytes

func (irs *IndexingRangeSet) ListMissingRangesInBytes(tr fdb.WritableTransaction, begin, end []byte) ([]RangeSetRange, error)

ListMissingRangesInBytes returns missing ranges within the given byte boundaries. Used by mutual indexing to check missing ranges within a fragment.

type Int64Evaluator

type Int64Evaluator interface {
	EvaluateInt64(record *FDBStoredRecord[proto.Message], msg proto.Message) (int64, bool, error)
}

Int64Evaluator extracts a single int64 value without boxing to any. Go's convT64 allocates for every non-zero int64→any conversion. This interface bypasses that by returning int64 directly.

type IntersectionChildResume

type IntersectionChildResume struct {
	Continuation []byte
	Started      bool
}

IntersectionChildResume is one child's decoded resume state, the output of decodeIntersectionContinuation. Started + (empty) Continuation classify the child as START (!Started → begin fresh), MID (Started + bytes → resume from bytes), or END (Started + empty → exhausted).

func DecodeIntersectionContinuation

func DecodeIntersectionContinuation(data []byte, n int) ([]IntersectionChildResume, error)

DecodeIntersectionContinuation is the exact inverse of buildIntersectionContinuation: it splits a parent IntersectionContinuation proto into n per-child resume states (RFC-071). A nil/empty continuation yields n all-fresh children (START). A proto that fails to parse, or whose child count does not match n, is a hard error (mirroring Java IntersectionCursorContinuation's RecordCoreArgumentException) — never a silent truncate. Consumed executor-side by executeIntersection / executeMultiIntersection.

type IsolationLevel

type IsolationLevel int

IsolationLevel represents the transaction isolation level. Matches Java's IsolationLevel enum.

Java Reference: com.apple.foundationdb.record.IsolationLevel Location: fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/IsolationLevel.java

func (IsolationLevel) IsSnapshot

func (level IsolationLevel) IsSnapshot() bool

IsSnapshot returns true if this isolation level uses snapshot reads.

Java equivalent: IsolationLevel.isSnapshot()

func (IsolationLevel) String

func (level IsolationLevel) String() string

String returns a human-readable representation of the isolation level.

type ItemSlot

type ItemSlot struct {
	HilbertValue *big.Int
	Point        Point
	KeySuffix    tuple.Tuple
	Value        tuple.Tuple
}

ItemSlot is a leaf node slot containing a data item.

func (ItemSlot) GetMBR

func (s ItemSlot) GetMBR() MBR

GetMBR returns the MBR for this item (a degenerate point MBR).

func (ItemSlot) ItemKey

func (s ItemSlot) ItemKey() tuple.Tuple

ItemKey returns the combined item key (point coordinates + suffix).

type KVCallback

type KVCallback func(keyLen, valueLen int)

KVCallback is called for each raw FDB key-value pair read during iteration. Used for byte scan limiting — the callback receives the raw key and value lengths before deserialization. Matches Java's Consumer<KeyValue> callback passed to BunchedMapMultiIterator.

type KeyExpression

type KeyExpression interface {
	// Evaluate extracts key tuples from a record.
	// Returns a list of key tuples (each tuple is a []any).
	// Single-valued expressions return one tuple; fan-out expressions
	// (e.g. repeated fields) return multiple tuples.
	//
	// record is the top-level stored record context (provides version, PK, etc.).
	// msg is the current message being evaluated (changes during nesting into sub-messages).
	// Either or both may be nil.
	//
	// Matches Java's KeyExpression.evaluateMessage(FDBRecord, Message) -> List<Key.Evaluated>.
	Evaluate(record *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

	// FieldNames returns the field names this expression accesses
	FieldNames() []string

	// ColumnSize returns the number of tuple elements this expression produces.
	// Matches Java's KeyExpression.getColumnSize().
	ColumnSize() int

	// ToKeyExpression serializes this expression to its protobuf representation.
	// Matches Java's KeyExpression.toKeyExpression().
	ToKeyExpression() *gen.KeyExpression
}

KeyExpression represents an expression that extracts key components from a record. Matches Java's KeyExpression interface which returns List<Key.Evaluated>.

func Concat

func Concat(exprs ...KeyExpression) KeyExpression

Concat creates a composite key from multiple expressions

func EmptyKey

func EmptyKey() KeyExpression

EmptyKey creates a key expression that produces an empty tuple.

func FanOut

func FanOut(name string) KeyExpression

FanOut creates a key expression for a repeated field that produces one index entry per repeated value. Matches Java's Key.Expressions.field("name", FanType.FanOut).

func Field

func Field(name string) KeyExpression

Field creates a key expression that extracts a single (non-repeated) field.

func FieldConcatenate

func FieldConcatenate(name string) KeyExpression

FieldConcatenate creates a key expression for a repeated field that collects all repeated values into a single tuple element. Matches Java's Key.Expressions.field("name", FanType.Concatenate). This is the argument shape a CARDINALITY() index uses: the whole array is materialised into one Key.Evaluated so its element count can be taken.

func GetNestedExpression

func GetNestedExpression(expr KeyExpression) KeyExpression

GetNestedExpression returns the nested expression of a RecordTypeKeyExpression

func KeyExpressionFromProto

func KeyExpressionFromProto(expr *gen.KeyExpression) (KeyExpression, error)

KeyExpressionFromProto deserializes a protobuf KeyExpression to a Go KeyExpression. Exactly one field must be set. Matches Java's KeyExpression.fromProto().

func Nest

func Nest(parentField string, child KeyExpression) KeyExpression

Nest creates a nesting expression: navigate into a message field and evaluate the child expression on the sub-message. Matches Java's field("parent").nest("child").

func NestFanOut

func NestFanOut(parentField string, child KeyExpression) KeyExpression

NestFanOut creates a nesting expression for a repeated message field. Each element of the repeated field is evaluated with the child expression, producing fan-out. Matches Java's field("parent", FanType.FanOut).nest(child).

type KeyExpressionError

type KeyExpressionError struct {
	Message string
}

KeyExpressionError is returned when a key expression evaluation fails. Matches Java's com.apple.foundationdb.record.metadata.expressions.KeyExpression.InvalidExpressionException.

func (*KeyExpressionError) Error

func (e *KeyExpressionError) Error() string

type KeyWithValueExpression

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

KeyWithValueExpression wraps an inner key expression and splits its evaluated columns into a "key" portion and a "value" portion. The key portion (columns 0..splitPoint-1) is stored in the FDB key, and the value portion (columns splitPoint..end) is stored in the FDB value. This enables "covering indexes" where additional query-relevant columns can be read without fetching the record. Matches Java's com.apple.foundationdb.record.metadata.expressions.KeyWithValueExpression.

func KeyWithValue

func KeyWithValue(inner KeyExpression, splitPoint int) *KeyWithValueExpression

KeyWithValue creates a KeyWithValueExpression. splitPoint is the number of leading columns that go into the FDB key; remaining columns go into the value. Matches Java's Key.Expressions.keyWithValue(inner, splitPoint).

func (*KeyWithValueExpression) ColumnSize

func (k *KeyWithValueExpression) ColumnSize() int

ColumnSize returns the split point — only key columns count, not value columns. Matches Java's KeyWithValueExpression.getColumnSize().

func (*KeyWithValueExpression) Evaluate

func (k *KeyWithValueExpression) Evaluate(record *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

Evaluate delegates to the inner key expression. The key/value split is only applied when writing/reading index entries, not during evaluation.

func (*KeyWithValueExpression) FieldNames

func (k *KeyWithValueExpression) FieldNames() []string

FieldNames delegates to the inner key expression.

func (*KeyWithValueExpression) InnerKey

func (k *KeyWithValueExpression) InnerKey() KeyExpression

InnerKey returns the wrapped key expression.

func (*KeyWithValueExpression) SplitEvaluatedKey

func (k *KeyWithValueExpression) SplitEvaluatedKey(fullKey []any) (keyPart []any, valuePart []any)

SplitEvaluatedKey splits a full evaluated result into key and value portions. key = columns[0:splitPoint], value = columns[splitPoint:]. Matches Java's KeyWithValueExpression.getKey() / getValue().

func (*KeyWithValueExpression) SplitPoint

func (k *KeyWithValueExpression) SplitPoint() int

SplitPoint returns the number of leading columns that form the key portion.

func (*KeyWithValueExpression) ToKeyExpression

func (k *KeyWithValueExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes KeyWithValueExpression to proto. Matches Java's KeyWithValueExpression.toKeyExpression().

type ListKeyExpression

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

ListKeyExpression combines multiple child expressions, producing nested tuples for each child's result (unlike Then/Concat which flattens). Each child's evaluation result is wrapped as a nested tuple element. Matches Java's com.apple.foundationdb.record.metadata.expressions.ListKeyExpression.

func ListExpr

func ListExpr(children ...KeyExpression) *ListKeyExpression

ListExpr creates a ListKeyExpression from the given children.

func (*ListKeyExpression) ColumnSize

func (l *ListKeyExpression) ColumnSize() int

ColumnSize returns the number of children — each child contributes one column (as a nested tuple element). Matches Java's ListKeyExpression.getColumnSize().

func (*ListKeyExpression) Evaluate

func (l *ListKeyExpression) Evaluate(record *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

Evaluate computes the cross-product of all child expression results, wrapping each child's result as a nested tuple.Tuple. Each child's Key.Evaluated values become a single nested tuple element in the result.

This matches Java's ListKeyExpression.evaluateMessage() + combine(), where childValue.toTupleAppropriateList() is added as a single List<Object> element that becomes a nested Tuple when serialized.

IMPORTANT: Child values must be wrapped as tuple.Tuple (named type), NOT bare []any. The FDB tuple packer's type switch uses `case Tuple:` which only matches the named type. Bare []any causes a runtime panic during Pack().

func (*ListKeyExpression) FieldNames

func (l *ListKeyExpression) FieldNames() []string

FieldNames returns all field names from child expressions.

func (*ListKeyExpression) GetChildren

func (l *ListKeyExpression) GetChildren() []KeyExpression

GetChildren returns the child expressions.

func (*ListKeyExpression) ToKeyExpression

func (l *ListKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes ListKeyExpression to proto. Matches Java's ListKeyExpression.toKeyExpression().

type LiteralKeyExpression

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

LiteralKeyExpression represents a static constant value in a key expression. The value does not depend on the record — it evaluates to the same fixed value for every record. Primary use case: passing static arguments to function key expressions, or creating composite indexes with a fixed prefix. Matches Java's LiteralKeyExpression.

func Literal

func Literal(value any) *LiteralKeyExpression

Literal creates a key expression that always evaluates to the given constant value. Supported types: nil, int, int32, int64, float32, float64, bool, string, []byte. Matches Java's Key.Expressions.value(Object).

func (*LiteralKeyExpression) ColumnSize

func (l *LiteralKeyExpression) ColumnSize() int

ColumnSize returns 1 — a literal expression produces a single tuple element.

func (*LiteralKeyExpression) Evaluate

Evaluate returns the constant value regardless of the record. Matches Java's LiteralKeyExpression.evaluateMessage() which ignores the record parameter.

func (*LiteralKeyExpression) FieldNames

func (l *LiteralKeyExpression) FieldNames() []string

FieldNames returns an empty slice — literal expressions don't access any fields.

func (*LiteralKeyExpression) GetValue

func (l *LiteralKeyExpression) GetValue() any

GetValue returns the constant value held by this expression.

func (*LiteralKeyExpression) ToKeyExpression

func (l *LiteralKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes LiteralKeyExpression to proto. Matches Java's LiteralKeyExpression.toKeyExpression().

type MBR

type MBR struct {
	Low  []int64
	High []int64
}

MBR is a minimum bounding rectangle for N dimensions. Stored as [low0, low1, ..., lowN-1, high0, high1, ..., highN-1].

func MBRFromPoint

func MBRFromPoint(p Point) MBR

MBRFromPoint creates a degenerate MBR containing only a single point.

func MBRFromTuple

func MBRFromTuple(t tuple.Tuple, numDimensions int) (MBR, error)

MBRFromTuple deserializes an MBR from a flat tuple.

func (MBR) ContainsPoint

func (m MBR) ContainsPoint(p Point) bool

ContainsPoint returns true if the MBR contains the given point.

func (MBR) NumDimensions

func (m MBR) NumDimensions() int

NumDimensions returns the number of dimensions.

func (MBR) Overlaps

func (m MBR) Overlaps(other MBR) bool

Overlaps returns true if this MBR overlaps with another. Returns false if the MBRs have different numbers of dimensions.

func (MBR) Union

func (m MBR) Union(other MBR) MBR

Union returns the smallest MBR containing both this and other. If the MBRs have different numbers of dimensions, returns self unchanged.

type MemoryLimitExceededError

type MemoryLimitExceededError struct {
	// Used is the running memory total (in bytes) at the point the budget
	// was breached — i.e. the would-be total INCLUDING the charge that
	// tripped it.
	Used int64
	// Limit is the configured statement-wide memory byte budget.
	Limit int64
}

MemoryLimitExceededError is returned when a statement's accounted in-memory buffering exceeds the statement-wide memory byte budget (RFC-130). It is a per-statement resource-limit error in the same family as the scan/byte/time limits — the relational layer maps it to SQLSTATE 54F01 (ErrCodeExecutionLimitReached), matching Java's reuse of that SQLSTATE for resource limits (there is no memory-specific SQLSTATE in Java either).

func (*MemoryLimitExceededError) Error

func (e *MemoryLimitExceededError) Error() string

type MetaDataError

type MetaDataError struct {
	Message string
}

MetaDataError is returned for metadata validation failures. Matches Java's com.apple.foundationdb.record.metadata.MetaDataException.

func (*MetaDataError) Error

func (e *MetaDataError) Error() string

type MetaDataEvolutionError

type MetaDataEvolutionError struct {
	Message string
}

MetaDataEvolutionError describes a schema evolution violation.

func (*MetaDataEvolutionError) Error

func (e *MetaDataEvolutionError) Error() string

type MetaDataEvolutionValidator

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

MetaDataEvolutionValidator validates that schema changes between an old and new RecordMetaData are safe. Prevents accidental data corruption from incompatible schema evolution.

Matches Java's com.apple.foundationdb.record.metadata.MetaDataEvolutionValidator.

func DefaultMetaDataEvolutionValidator

func DefaultMetaDataEvolutionValidator() *MetaDataEvolutionValidator

DefaultMetaDataEvolutionValidator returns the strictest validator (all options false). Matches Java's MetaDataEvolutionValidator.getDefaultInstance().

func (*MetaDataEvolutionValidator) Validate

func (v *MetaDataEvolutionValidator) Validate(oldMetaData, newMetaData *RecordMetaData) error

Validate checks that evolving from oldMetaData to newMetaData is safe. Returns nil if the evolution is valid, or an error describing the violation. Matches Java's MetaDataEvolutionValidator.validate().

type MetaDataEvolutionValidatorBuilder

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

MetaDataEvolutionValidatorBuilder builds a MetaDataEvolutionValidator with custom options.

func NewMetaDataEvolutionValidator

func NewMetaDataEvolutionValidator() *MetaDataEvolutionValidatorBuilder

NewMetaDataEvolutionValidator returns a builder for configuring the validator.

func (*MetaDataEvolutionValidatorBuilder) Build

func (*MetaDataEvolutionValidatorBuilder) SetAllowDeprecatedFieldRenames

func (b *MetaDataEvolutionValidatorBuilder) SetAllowDeprecatedFieldRenames(v bool) *MetaDataEvolutionValidatorBuilder

SetAllowDeprecatedFieldRenames permits renaming a field when the old or new field is deprecated (a narrower allowance than SetAllowFieldRenames). Matches Java's setAllowDeprecatedFieldRenames.

func (*MetaDataEvolutionValidatorBuilder) SetAllowFieldRenames

SetAllowFieldRenames permits any field to be renamed (same field number, new name) across a metadata evolution. Matches Java's setAllowFieldRenames.

func (*MetaDataEvolutionValidatorBuilder) SetAllowIndexRebuilds

func (*MetaDataEvolutionValidatorBuilder) SetAllowMissingFormerIndexNames

func (b *MetaDataEvolutionValidatorBuilder) SetAllowMissingFormerIndexNames(v bool) *MetaDataEvolutionValidatorBuilder

func (*MetaDataEvolutionValidatorBuilder) SetAllowNoSinceVersion

func (*MetaDataEvolutionValidatorBuilder) SetAllowNoVersionChange

func (*MetaDataEvolutionValidatorBuilder) SetAllowOlderFormerIndexAddedVersion

func (b *MetaDataEvolutionValidatorBuilder) SetAllowOlderFormerIndexAddedVersion(v bool) *MetaDataEvolutionValidatorBuilder

func (*MetaDataEvolutionValidatorBuilder) SetAllowUndeprecatingFields

SetAllowUndeprecatingFields permits a field that was deprecated to become non-deprecated. Matches Java's setAllowUndeprecatingFields.

func (*MetaDataEvolutionValidatorBuilder) SetAllowUnsplitToSplit

func (*MetaDataEvolutionValidatorBuilder) SetDisallowTypeRenames

type MetaDataVersionMustIncreaseError

type MetaDataVersionMustIncreaseError struct {
	OldVersion int32
	NewVersion int32
}

MetaDataVersionMustIncreaseError is returned by SaveRecordMetaData when the new metadata's version is not strictly greater than the stored one. This check is unconditional — it does not consult the evolution validator's allowNoVersionChange knob, exactly like Java, where saveAndSetCurrent throws before the validator ever runs. Matches Java's MetaDataException("meta-data version must increase") with log keys OLD / NEW.

func (*MetaDataVersionMustIncreaseError) Error

type MetaDataVersionStampStoreStateCache

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

MetaDataVersionStampStoreStateCache caches store state and validates entries using FDB's metadata version stamp (a system key that changes on every mutation). Matches Java's MetaDataVersionStampStoreStateCache.

func NewMetaDataVersionStampStoreStateCache

func NewMetaDataVersionStampStoreStateCache(opts ...MetaDataVersionStampStoreStateCacheOption) *MetaDataVersionStampStoreStateCache

NewMetaDataVersionStampStoreStateCache creates a new cache with optional configuration.

func (*MetaDataVersionStampStoreStateCache) Clear

Clear removes all cached entries.

func (*MetaDataVersionStampStoreStateCache) Get

Get retrieves store state, using the cache when the metadata version stamp matches. Matches Java's MetaDataVersionStampStoreStateCache.get().

type MetaDataVersionStampStoreStateCacheOption

type MetaDataVersionStampStoreStateCacheOption func(*MetaDataVersionStampStoreStateCache)

MetaDataVersionStampStoreStateCacheOption configures the cache.

func WithExpireAfterAccess

WithExpireAfterAccess sets the TTL for cache entries since last access. Default: 1 minute (matches Java's default).

func WithMaxSize

WithMaxSize sets the maximum number of entries in the cache. Default: 500 (matches Java's default).

type NestingKeyExpression

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

NestingKeyExpression navigates into a nested protobuf message and evaluates a child expression against it. Matches Java's NestingKeyExpression.

Example: Nest("flower", Field("type")) indexes the "type" field inside a nested "flower" message.

For repeated message fields, use NestFanOut to fan out over each sub-message.

func (*NestingKeyExpression) ColumnSize

func (n *NestingKeyExpression) ColumnSize() int

ColumnSize returns the child's column size — the parent message field doesn't contribute a tuple element.

func (*NestingKeyExpression) Evaluate

func (n *NestingKeyExpression) Evaluate(record *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

Evaluate navigates into the parent message field and evaluates the child expression on the sub-message(s).

func (*NestingKeyExpression) FieldNames

func (n *NestingKeyExpression) FieldNames() []string

FieldNames returns the parent field name plus child field names.

func (*NestingKeyExpression) ToKeyExpression

func (n *NestingKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes a NestingKeyExpression to proto. Matches Java's NestingKeyExpression.toKeyExpression().

type NoNextReason

type NoNextReason int

NoNextReason indicates why a cursor stopped producing records

const (
	// SourceExhausted means the cursor reached the end of its data
	SourceExhausted NoNextReason = iota
	// ReturnLimitReached means the cursor hit its row limit
	ReturnLimitReached
	// ByteLimitReached means the cursor hit its byte scan limit
	ByteLimitReached
	// TimeLimitReached means the cursor hit its time limit
	TimeLimitReached
	// ScanLimitReached means the cursor hit its key-value scan limit
	ScanLimitReached
)

func (NoNextReason) IsLimitReached

func (r NoNextReason) IsLimitReached() bool

IsLimitReached returns true if the cursor stopped due to any kind of limit

func (NoNextReason) IsOutOfBand

func (r NoNextReason) IsOutOfBand() bool

IsOutOfBand returns true if this reason represents an out-of-band completion (not solely dependent on the records returned)

func (NoNextReason) IsSourceExhausted

func (r NoNextReason) IsSourceExhausted() bool

IsSourceExhausted returns true if there is no more data available

type NodeKind

type NodeKind byte

NodeKind identifies a node as leaf or intermediate.

const (
	NodeKindLeaf         NodeKind = 0x00
	NodeKindIntermediate NodeKind = 0x01
)

type OnlineIndexer

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

OnlineIndexer builds indexes on existing data across multiple transactions. Each transaction processes a chunk of records, tracks progress via IndexingRangeSet, and the build resumes from where it left off if interrupted.

Supports four modes:

  • BY_RECORDS (default, single target): scans all records in primary key order
  • BY_INDEX (single target): scans an existing readable VALUE index to find records
  • MULTI_TARGET_BY_RECORDS: scans records once, builds multiple indexes simultaneously
  • MUTUAL_BY_RECORDS: concurrent multi-process building with fragment-based work division

Matches Java's OnlineIndexer with IndexingByRecords, IndexingByIndex, IndexingMultiTargetByRecords, and IndexingMutuallyByRecords.

func (*OnlineIndexer) BlockIndex

func (oi *OnlineIndexer) BlockIndex(ctx context.Context, blockID string, ttl time.Duration) error

BlockIndex sets the block flag on the indexing stamp for all target indexes. A blocked stamp prevents other indexers from continuing the build. blockID is an optional identifier for the block reason. ttl is the time-to-live for the block; zero means permanent. Matches Java's IndexingBase.performIndexingStampOperation(BLOCK, ...).

func (*OnlineIndexer) BuildIndex

func (oi *OnlineIndexer) BuildIndex(ctx context.Context) (int64, error)

BuildIndex runs the full index build: marks WRITE_ONLY, builds all records, then marks READABLE. Returns the number of records indexed. Matches Java's OnlineIndexer.buildIndex().

func (*OnlineIndexer) MarkReadableIfBuilt

func (oi *OnlineIndexer) MarkReadableIfBuilt(ctx context.Context) (bool, error)

MarkReadableIfBuilt checks each target index and marks it READABLE if fully built. Returns true if all target indexes are now READABLE. This is an idempotent operation — safe to call repeatedly. Matches Java's IndexingBase.markReadableIfBuilt().

func (*OnlineIndexer) QueryIndexingStamps

func (oi *OnlineIndexer) QueryIndexingStamps(ctx context.Context) (map[string]*gen.IndexBuildIndexingStamp, error)

QueryIndexingStamps returns the indexing stamps for all target indexes. Returns a map of index name → stamp. Nil stamps are returned as a NONE method stamp. Matches Java's IndexingBase.performIndexingStampOperation(QUERY, ...).

func (*OnlineIndexer) UnblockIndex

func (oi *OnlineIndexer) UnblockIndex(ctx context.Context, blockID string) error

UnblockIndex clears the block flag on the indexing stamp for all target indexes. If blockID is non-empty, only unblocks stamps with a matching blockID. Matches Java's IndexingBase.performIndexingStampOperation(UNBLOCK, ...).

type OnlineIndexerBuilder

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

OnlineIndexerBuilder constructs an OnlineIndexer.

func NewOnlineIndexerBuilder

func NewOnlineIndexerBuilder() *OnlineIndexerBuilder

NewOnlineIndexerBuilder creates a new builder.

func (*OnlineIndexerBuilder) AddTargetIndex

func (b *OnlineIndexerBuilder) AddTargetIndex(index *Index) *OnlineIndexerBuilder

AddTargetIndex adds a target index for multi-target building. Mutually exclusive with SetIndex. Matches Java's OnlineIndexer.Builder.addTargetIndex().

func (*OnlineIndexerBuilder) Build

func (b *OnlineIndexerBuilder) Build() (*OnlineIndexer, error)

Build creates the OnlineIndexer. Matches Java's OnlineIndexer.Builder.build(): validates, deduplicates, and sorts target indexes by name (the alphabetically-first index becomes the "primary" that drives range tracking).

func (*OnlineIndexerBuilder) SetDatabase

SetDatabase sets the FDB database.

func (*OnlineIndexerBuilder) SetEnforcedPostTransactionDelay

func (b *OnlineIndexerBuilder) SetEnforcedPostTransactionDelay(ms int) *OnlineIndexerBuilder

SetEnforcedPostTransactionDelay sets a fixed delay in milliseconds applied after each build transaction. When positive, it is used INSTEAD of the records-per-second throttle. Default 0 disables it (records-per-second behaviour). Matches Java's OnlineIndexer.Builder.setEnforcedPostTransactionDelay().

func (*OnlineIndexerBuilder) SetIndex

func (b *OnlineIndexerBuilder) SetIndex(index *Index) *OnlineIndexerBuilder

SetIndex sets a single target index to build. Mutually exclusive with AddTargetIndex/SetTargetIndexes.

func (*OnlineIndexerBuilder) SetLeaseLengthMs

func (b *OnlineIndexerBuilder) SetLeaseLengthMs(ms int64) *OnlineIndexerBuilder

SetLeaseLengthMs sets the heartbeat lease duration in milliseconds. If a heartbeat is not updated within this duration, the process is presumed dead. Default is 30000 (30 seconds). Only relevant for non-mutual mode; in mutual mode heartbeats are written but not checked. Matches Java's OnlineIndexer.IndexingPolicy.setLeaseLengthMillis().

func (*OnlineIndexerBuilder) SetLimit

func (b *OnlineIndexerBuilder) SetLimit(limit int) *OnlineIndexerBuilder

SetLimit sets the maximum number of records to process per transaction.

func (*OnlineIndexerBuilder) SetLogger

func (b *OnlineIndexerBuilder) SetLogger(logger *slog.Logger) *OnlineIndexerBuilder

SetLogger sets the slog.Logger that receives the indexer's operational progress events. A nil logger (the default) falls back to slog.Default() at log time, mirroring the client's WithLogger convention (RFC-097).

func (*OnlineIndexerBuilder) SetMarkReadable

func (b *OnlineIndexerBuilder) SetMarkReadable(v bool) *OnlineIndexerBuilder

SetMarkReadable controls whether BuildIndex marks the index readable when the build completes (default true). With false, the build populates the index but leaves it WRITE_ONLY with its build stamp and progress counter intact — matching Java's OnlineIndexer.buildIndex(boolean markReadable).

func (*OnlineIndexerBuilder) SetMaxRetries

func (b *OnlineIndexerBuilder) SetMaxRetries(maxRetries int) *OnlineIndexerBuilder

SetMaxRetries sets the maximum number of retries per range on transient FDB errors. When a range build fails with a transient error, the indexer retries with a halved limit. Default is 0 (no retries — errors propagate immediately). Matches Java's OnlineIndexer.Builder.setMaxRetries() (default 100 in Java).

func (*OnlineIndexerBuilder) SetMetaData

SetMetaData sets the record metadata.

func (*OnlineIndexerBuilder) SetMutualIndexing

func (b *OnlineIndexerBuilder) SetMutualIndexing() *OnlineIndexerBuilder

SetMutualIndexing enables concurrent/mutual index building mode. Multiple indexer processes can run simultaneously, each building different fragments of the key space. Fragments are determined by FDB shard boundaries. Matches Java's OnlineIndexer.Builder.setMutualIndexing().

func (*OnlineIndexerBuilder) SetMutualIndexingBoundaries

func (b *OnlineIndexerBuilder) SetMutualIndexingBoundaries(boundaries [][]byte) *OnlineIndexerBuilder

SetMutualIndexingBoundaries enables mutual mode with pre-set fragment boundaries. Each boundary is a packed tuple representing a primary key at which to split the key space. If nil/empty, the entire key space is treated as a single fragment. Matches Java's OnlineIndexer.Builder.setMutualIndexingBoundaries().

func (*OnlineIndexerBuilder) SetPolicy

SetPolicy sets the indexing policy for stamp conflict resolution. Matches Java's OnlineIndexer.Builder.setIndexingPolicy().

func (*OnlineIndexerBuilder) SetProgressLogIntervalMillis

func (b *OnlineIndexerBuilder) SetProgressLogIntervalMillis(ms int64) *OnlineIndexerBuilder

SetProgressLogIntervalMillis sets the throttle for the per-range "Indexer: Built Range" progress log. Matches Java OnlineIndexer.Builder.setProgressLogIntervalMillis():

  • a negative value (the default, -1) disables progress logging;
  • 0 logs after every range;
  • a positive value logs at most once per that many milliseconds.

Events go to the logger set via SetLogger (or slog.Default()) at INFO.

func (*OnlineIndexerBuilder) SetRecordTypes

func (b *OnlineIndexerBuilder) SetRecordTypes(types ...string) *OnlineIndexerBuilder

SetRecordTypes sets which record types to index. If empty, indexes all types that have this index defined. Not allowed with multi-target building.

func (*OnlineIndexerBuilder) SetRecordsPerSecond

func (b *OnlineIndexerBuilder) SetRecordsPerSecond(rps int) *OnlineIndexerBuilder

SetRecordsPerSecond sets the inter-transaction rate limit. The indexer will sleep between transactions to maintain approximately this rate. Default is 10,000 records/second (matching Java). Set to 0 for unlimited. Matches Java's OnlineIndexer.Builder.setRecordsPerSecond().

func (*OnlineIndexerBuilder) SetSourceIndex

func (b *OnlineIndexerBuilder) SetSourceIndex(index *Index) *OnlineIndexerBuilder

SetSourceIndex sets the source index for the BY_INDEX strategy. The source index must be a READABLE VALUE index whose root expression does not create duplicates. Both source and target must apply to exactly one record type, and the target's type must be a superset of the source's. Not allowed with multi-target building. Matches Java's OnlineIndexer.Builder.setSourceIndex().

func (*OnlineIndexerBuilder) SetSubspace

SetSubspace sets the store subspace.

func (*OnlineIndexerBuilder) SetTargetIndexes

func (b *OnlineIndexerBuilder) SetTargetIndexes(indexes []*Index) *OnlineIndexerBuilder

SetTargetIndexes sets multiple target indexes for multi-target building. Mutually exclusive with SetIndex. Matches Java's OnlineIndexer.Builder.setTargetIndexes().

func (*OnlineIndexerBuilder) SetTimeLimit

SetTimeLimit sets the overall time limit for the entire build. If the build exceeds this duration, BuildIndex returns a TimeLimitExceededError after the current range completes. Zero means unlimited (default). Matches Java's OnlineIndexer.Builder.setTimeLimitMilliseconds().

type OrderDirection

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

OrderDirection specifies how tuple values are encoded for ordered storage. Matches Java's TupleOrdering.Direction enum.

type PartlyBuiltError

type PartlyBuiltError struct {
	IndexName     string
	SavedStamp    string // string representation of the saved stamp
	ExpectedStamp string // string representation of the expected stamp
	Message       string
}

PartlyBuiltError is returned when an OnlineIndexer encounters an index that was partly built by another method or is blocked from continuing. Matches Java's com.apple.foundationdb.record.provider.foundationdb.IndexingBase.PartlyBuiltException.

func (*PartlyBuiltError) Error

func (e *PartlyBuiltError) Error() string

type PassThroughRecordStoreStateCache

type PassThroughRecordStoreStateCache struct{}

PassThroughRecordStoreStateCache is a no-op cache that always loads from FDB. This is the default behavior. Matches Java's PassThroughRecordStoreStateCache.

func (*PassThroughRecordStoreStateCache) Clear

Clear is a no-op.

func (*PassThroughRecordStoreStateCache) Get

Get always loads fresh state from FDB. Skips the metadata version stamp read since PassThrough has no cache to validate against.

type Point

type Point struct {
	Coordinates tuple.Tuple
}

Point represents an N-dimensional point with int64 coordinates. Null coordinates are represented as nil in the tuple.

func (Point) Coordinate

func (p Point) Coordinate(dim int) int64

Coordinate returns the coordinate at the given dimension index, or MinInt64 if nil.

func (Point) NumDimensions

func (p Point) NumDimensions() int

NumDimensions returns the number of dimensions.

type PostCommitFunc

type PostCommitFunc func()

PostCommitFunc is a callback that runs after a successful commit. Matches Java's PostCommit interface.

type RTree

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

RTree is a Hilbert R-tree backed by FDB. Matches Java's com.apple.foundationdb.async.rtree.RTree.

func NewRTree

func NewRTree(storage *rtreeStorage, config RTreeConfig) (*RTree, error)

NewRTree creates a new R-tree. Returns an error if config is invalid.

func (*RTree) Clear

func (rt *RTree) Clear(tx fdb.WritableTransaction) error

Clear removes all data from the R-tree.

func (*RTree) Delete

func (rt *RTree) Delete(tx fdb.WritableTransaction, point Point, keySuffix tuple.Tuple) error

Delete removes an item from the R-tree. Matches Java's RTree.delete().

func (*RTree) InsertOrUpdate

func (rt *RTree) InsertOrUpdate(tx fdb.WritableTransaction, point Point, keySuffix tuple.Tuple, value tuple.Tuple) error

InsertOrUpdate inserts a new item or updates an existing one. Matches Java's RTree.insertOrUpdate().

func (*RTree) Scan

func (rt *RTree) Scan(tx fdb.ReadTransaction, lastHV *big.Int, lastKey tuple.Tuple, mbrPredicate func(MBR) bool) ([]ItemSlot, error)

Scan returns all items matching the MBR predicate, starting after (lastHV, lastKey). Items are returned in Hilbert value order. Convenience wrapper around ScanIterator.

func (*RTree) ScanIterator

func (rt *RTree) ScanIterator(tx fdb.ReadTransaction, lastHV *big.Int, lastKey tuple.Tuple, mbrPredicate func(MBR) bool) *RTreeIterator

ScanIterator returns a lazy iterator over items matching the MBR predicate, starting after (lastHV, lastKey). Items are yielded one at a time in Hilbert value order. Only fetches leaf nodes from FDB on demand.

type RTreeConfig

type RTreeConfig struct {
	MinM               int  // Min slots per non-root node (default 16)
	MaxM               int  // Max slots per node (default 32)
	SplitS             int  // Siblings involved in split/fuse (default 2)
	StoreHilbertValues bool // Store HV in leaf slots (default true)
	NumDimensions      int  // Number of spatial dimensions
}

RTreeConfig configures the R-tree behavior. Matches Java's RTree.Config.

func DefaultRTreeConfig

func DefaultRTreeConfig(numDimensions int) RTreeConfig

DefaultRTreeConfig returns the default R-tree configuration.

type RTreeIterator

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

RTreeIterator lazily walks the R-tree depth-first in Hilbert order, fetching one leaf node at a time from FDB.

func (*RTreeIterator) Next

func (it *RTreeIterator) Next() (ItemSlot, bool, error)

Next returns the next item from the iterator. Returns (item, true, nil) on success, (zero, false, nil) when exhausted, or (zero, false, err) on error.

type RangeSet

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

RangeSet tracks ranges of completed work in an FDB subspace. Wire-compatible with Java's com.apple.foundationdb.async.RangeSet.

func NewRangeSet

func NewRangeSet(ss subspace.Subspace) *RangeSet

NewRangeSet creates a RangeSet that stores data in the given subspace.

func (*RangeSet) Clear

func (rs *RangeSet) Clear(tr fdb.WritableTransaction)

Clear removes all ranges from the set.

func (*RangeSet) Contains

func (rs *RangeSet) Contains(tr fdb.WritableTransaction, key []byte) (bool, error)

Contains checks if key is in any range in the set. Adds a read conflict on the key for proper isolation.

func (*RangeSet) InsertRange

func (rs *RangeSet) InsertRange(tr fdb.WritableTransaction, begin, end []byte, requireEmpty bool) (bool, error)

InsertRange adds range [begin, end) to the set. If begin is nil, uses FIRST_KEY. If end is nil, uses FINAL_KEY. If requireEmpty is true, only inserts if the range is currently empty (atomic test-and-set). Returns true if the database was modified.

func (*RangeSet) IsEmpty

func (rs *RangeSet) IsEmpty(tr fdb.WritableTransaction) (bool, error)

IsEmpty returns true if no ranges have been inserted into this set.

func (*RangeSet) MissingRanges

func (rs *RangeSet) MissingRanges(tr fdb.WritableTransaction, begin, end []byte, limit int) ([]RangeSetRange, error)

MissingRanges returns the gaps (ranges not in the set) within [begin, end). If begin is nil, uses FIRST_KEY. If end is nil, uses FINAL_KEY. If limit <= 0, returns all gaps.

type RangeSetEmptyKeyError

type RangeSetEmptyKeyError struct{}

RangeSetEmptyKeyError is returned when a RangeSet operation receives an empty key.

func (*RangeSetEmptyKeyError) Error

func (e *RangeSetEmptyKeyError) Error() string

type RangeSetInvertedRangeError

type RangeSetInvertedRangeError struct {
	Begin []byte
	End   []byte
}

RangeSetInvertedRangeError is returned when begin > end in a range operation.

func (*RangeSetInvertedRangeError) Error

type RangeSetKeyTooLargeError

type RangeSetKeyTooLargeError struct {
	Key []byte
}

RangeSetKeyTooLargeError is returned when a key is >= \xff.

func (*RangeSetKeyTooLargeError) Error

func (e *RangeSetKeyTooLargeError) Error() string

type RangeSetRange

type RangeSetRange struct {
	Begin []byte
	End   []byte
}

RangeSetRange represents a gap (missing range) as [Begin, End).

type RankQuerier

type RankQuerier interface {
	RankForScore(score tuple.Tuple, nullsAreLow bool) (*int64, error)
	ScoreForRank(rank tuple.Tuple) (tuple.Tuple, error)
}

RankQuerier is the public interface for rank-based queries on a RANK index maintainer.

type RecordAlreadyExistsError

type RecordAlreadyExistsError struct {
	Message    string
	PrimaryKey any // tuple.Tuple, but using any to avoid import cycle
}

RecordAlreadyExistsError is returned when attempting to insert a record that already exists. Includes structured context matching Java's RecordAlreadyExistsException.

Java equivalent: com.apple.foundationdb.record.provider.foundationdb.RecordAlreadyExistsException Location: fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/provider/foundationdb/RecordAlreadyExistsException.java Java includes: LogMessageKeys.PRIMARY_KEY

func (*RecordAlreadyExistsError) Error

func (e *RecordAlreadyExistsError) Error() string

type RecordContextConfig

type RecordContextConfig struct {
	// TransactionTimeout is the timeout for the FDB transaction.
	// Zero means use FDB's default.
	TransactionTimeout time.Duration

	// Priority sets the transaction priority.
	Priority TransactionPriority

	// TransactionID is an optional identifier for tracing/debugging.
	TransactionID string

	// TransactionSizeWarnBytes triggers a warning when the approximate
	// transaction size exceeds this threshold. Zero disables the check.
	// FDB's hard limit is 10MB; a typical warning threshold is 8MB.
	TransactionSizeWarnBytes int64

	// TransactionSizeErrorBytes causes operations to return
	// TransactionSizeExceededError when the approximate transaction
	// size exceeds this threshold. Zero disables the check.
	// Setting this below FDB's 10MB limit lets callers commit early.
	TransactionSizeErrorBytes int64
}

RecordContextConfig holds configuration for creating FDBRecordContext instances. Matches Java's FDBRecordContextConfig.

type RecordCursor

type RecordCursor[T any] interface {
	// OnNext asynchronously returns the next result from this cursor
	OnNext(ctx context.Context) (RecordCursorResult[T], error)

	// Close releases any resources held by this cursor
	Close() error

	// IsClosed returns true if the cursor has been closed
	IsClosed() bool
}

RecordCursor is a generic async iterator over records

func Chained

func Chained[T any](
	generator func(prev *T) (*T, error),
	encode func(T) []byte,
	decode func([]byte) (T, bool),
	continuation []byte,
) RecordCursor[T]

Chained creates a cursor that produces values from a generator function. generator receives the previous value (nil for the first call) and returns the next value or nil to signal exhaustion. encode/decode serialize/deserialize values for continuations. Matches Java's ChainedCursor.

func ConcatCursors

func ConcatCursors[T any](first, second CursorFactory[T], continuation []byte) RecordCursor[T]

ConcatCursors concatenates two cursor factories: results from first, then second. Continuation tokens are wire-compatible with Java's ConcatCursor.

func Dedup

func Dedup[T any](
	innerFactory CursorFactory[T],
	equal func(a, b T) bool,
	pack func(T) []byte,
	unpack func([]byte) (T, bool),
	continuation []byte,
) RecordCursor[T]

Dedup creates a cursor that removes adjacent duplicate elements. equal compares two elements; pack/unpack serialize the last value for continuations. If pack is nil, continuation will not include lastValue. Matches Java's DedupCursor.

func Empty

func Empty[T any]() RecordCursor[T]

Empty returns a cursor that produces no results (source exhausted immediately).

func Fallback

func Fallback[T any](
	inner RecordCursor[T],
	fallbackFactory func(lastResult *RecordCursorResult[T]) RecordCursor[T],
) RecordCursor[T]

Fallback creates a cursor that falls back to an alternative on error. fallbackFactory receives the last successful result (nil if the inner cursor failed on its first call) and should return a cursor that resumes from there. Matches Java's FallbackCursor — one-shot fallback (fails permanently if the fallback cursor also errors).

func FlatMapPipelined

func FlatMapPipelined[T, V any](
	outerFactory CursorFactory[T],
	innerFactory func(T, []byte) RecordCursor[V],
	continuation []byte,
	pipelineSize int,
) RecordCursor[V]

FlatMapPipelined creates a cursor that flat-maps an outer cursor through an inner cursor factory. Matches Java's RecordCursor.flatMapPipelined().

Parameters:

  • outerFactory: creates the outer cursor from a continuation
  • innerFactory: given an outer value and optional inner continuation, creates an inner cursor
  • continuation: serialized FlatMapContinuation for resumption (nil to start fresh)
  • pipelineSize: accepted for API compat (Go processes sequentially)

func FlatMapPipelinedWithCheck

func FlatMapPipelinedWithCheck[T, V any](
	outerFactory CursorFactory[T],
	innerFactory func(T, []byte) RecordCursor[V],
	checkValueFunc func(T) []byte,
	continuation []byte,
	pipelineSize int,
) RecordCursor[V]

FlatMapPipelinedWithCheck is like FlatMapPipelined but with an optional check value function. The check value validates that the outer record hasn't changed between transactions when resuming from a continuation mid-inner-cursor.

func FromList

func FromList[T any](items []T) RecordCursor[T]

FromList creates a cursor from a slice. Matches Java's RecordCursor.fromList().

func FromListWithContinuation

func FromListWithContinuation[T any](items []T, continuation []byte) RecordCursor[T]

FromListWithContinuation creates a cursor from a slice, starting from a continuation. Matches Java's RecordCursor.fromList(list, continuation). Continuation format: 4-byte big-endian position (nil/empty = start from beginning). Java uses ByteBuffer.wrap(continuation).getInt() which reads first 4 bytes and throws BufferUnderflowException for continuations shorter than 4 bytes. Go returns an error from OnNext for invalid continuation lengths to match Java's fail-fast behavior.

func Intersection

func Intersection[T any](
	cursors []RecordCursor[T],
	compKeyFunc ComparisonKeyFunc[T],
	reverse bool,
) RecordCursor[T]

Intersection creates a merge-intersection cursor that returns only elements present in ALL child cursors (by comparison key). All cursors must be ordered by the same key. Returns the element from the first cursor when all match. Matches Java's IntersectionCursor.create().

func IntersectionMulti

func IntersectionMulti[T any](
	cursors []RecordCursor[T],
	compKeyFunc ComparisonKeyFunc[T],
	reverse bool,
) RecordCursor[[]T]

IntersectionMulti creates a merge-intersection cursor that returns, for each set of elements present in ALL child cursors (by comparison key), the list of those elements (index i is the element from child i). All cursors must be ordered by the same key. Matches Java's IntersectionMultiCursor.create().

func IntersectionMultiResume

func IntersectionMultiResume[T any](
	cursors []RecordCursor[T],
	compKeyFunc ComparisonKeyFunc[T],
	reverse bool,
	resume []IntersectionChildResume,
) RecordCursor[[]T]

IntersectionMultiResume is IntersectionMulti with per-child resume state (see IntersectionResume). resume may be nil (all children fresh).

func IntersectionResume

func IntersectionResume[T any](
	cursors []RecordCursor[T],
	compKeyFunc ComparisonKeyFunc[T],
	reverse bool,
	resume []IntersectionChildResume,
) RecordCursor[T]

IntersectionResume is Intersection with per-child resume state from DecodeIntersectionContinuation. Each child's cached continuation is seeded from resume[i] (START → fresh, MID → its bytes, END → end), so a resumed child re-encodes correctly on the next checkpoint (RFC-071). resume may be nil (all children fresh, == Intersection).

func LimitRowsCursor

func LimitRowsCursor[T any](cursor RecordCursor[T], n int) RecordCursor[T]

LimitRowsCursor wraps a cursor and limits to at most n elements. Matches Java's RecordCursor.limitRowsTo().

func MapCursor

func MapCursor[T, R any](cursor RecordCursor[T], fn func(T) R) RecordCursor[R]

MapCursor creates a cursor that transforms each value using the given function. Continuations from the inner cursor are passed through transparently.

func MapErrCursor

func MapErrCursor[T, R any](cursor RecordCursor[T], fn func(T) (R, error)) RecordCursor[R]

MapErrCursor creates a cursor that transforms each value using a function that can return an error. If the transform function returns an error, iteration stops with that error. Continuations from the inner cursor are passed through. Matches Java's MapResultCursor with checked exceptions.

func NewAutoContinuingCursor

func NewAutoContinuingCursor[T any](
	runner *FDBDatabaseRunner,
	generator func(*FDBRecordContext, []byte) RecordCursor[T],
	maxRetries int,
) RecordCursor[T]

NewAutoContinuingCursor creates a cursor that automatically creates new transactions when the inner cursor stops before exhaustion (e.g., time limit, scan limit). Matches Java's AutoContinuingCursor.

Parameters:

  • runner: provides transaction creation and context configuration
  • generator: creates a cursor within a transaction context from a continuation
  • maxRetries: maximum retries on transient FDB errors (0 = no retries)

func OrElse

func OrElse[T any](primary RecordCursor[T], alternative func() RecordCursor[T]) RecordCursor[T]

OrElse returns the primary cursor if it has results, otherwise falls back to the alternative cursor. Matches Java's RecordCursor.orElse().

func OrElseWithContinuation

func OrElseWithContinuation[T any](
	primaryFactory CursorFactory[T],
	alternativeFactory CursorFactory[T],
	continuation []byte,
) RecordCursor[T]

OrElseWithContinuation creates an OrElse cursor with continuation support. Matches Java's OrElseCursor with OrElseContinuation proto serialization. Both primary and alternative are cursor factories that accept continuation bytes for cross-transaction resume.

func SkipCursor

func SkipCursor[T any](cursor RecordCursor[T], n int) RecordCursor[T]

SkipCursor wraps a cursor and skips the first n elements. Matches Java's RecordCursor.skip().

func SkipThenLimit

func SkipThenLimit[T any](cursor RecordCursor[T], skip, limit int) RecordCursor[T]

SkipThenLimit is a convenience that skips n elements then limits to m. Matches Java's RecordCursor.skipThenLimit().

func Union

func Union[T any](
	cursors []RecordCursor[T],
	compKeyFunc ComparisonKeyFunc[T],
	reverse bool,
) RecordCursor[T]

Union creates a merge-union cursor that combines multiple ordered cursors. All child cursors must be ordered by the same comparison key. The compKeyFunc extracts the comparison key from each element. Elements with duplicate keys across cursors are deduplicated (first cursor wins). Matches Java's UnionCursor.create().

type RecordCursorContinuation

type RecordCursorContinuation interface {
	// ToBytes serializes this continuation to a byte array.
	// Returns (nil, nil) if this is an end continuation.
	ToBytes() ([]byte, error)

	// IsEnd returns true if this represents the end of iteration
	IsEnd() bool
}

RecordCursorContinuation represents the position of a cursor for resumption

type RecordCursorResult

type RecordCursorResult[T any] struct {
	// contains filtered or unexported fields
}

RecordCursorResult represents the result of a cursor's OnNext() call.

Invariants (matching Java's RecordCursorResult):

  • A result WITH a value (HasNext=true) must NOT have an EndContinuation
  • A result with SourceExhausted MUST have an EndContinuation
  • A result with any other NoNextReason must NOT have an EndContinuation

func MapResult

func MapResult[T, R any](result RecordCursorResult[T], fn func(T) R) RecordCursorResult[R]

MapResult transforms a result's value using the given function. If the result has no value (HasNext() is false), returns a no-next result with the same reason and continuation. Go generics require this as a standalone function rather than a method. Matches Java's RecordCursorResult.map().

func NewResultNoNext

func NewResultNoNext[T any](reason NoNextReason, continuation RecordCursorContinuation) RecordCursorResult[T]

NewResultNoNext creates a result indicating no more records. Enforces invariants matching Java's RecordCursorResult.withoutNextValue():

  • EndContinuation is only valid with SourceExhausted
  • SourceExhausted requires an EndContinuation

func NewResultWithValue

func NewResultWithValue[T any](value T, continuation RecordCursorContinuation) RecordCursorResult[T]

NewResultWithValue creates a result with a value. Panics if continuation is an EndContinuation — a value result must always have a resumable continuation. Matches Java's RecordCursorResult.withNextValue().

func (RecordCursorResult[T]) GetContinuation

func (r RecordCursorResult[T]) GetContinuation() RecordCursorContinuation

GetContinuation returns the continuation for resuming the cursor

func (RecordCursorResult[T]) GetNoNextReason

func (r RecordCursorResult[T]) GetNoNextReason() NoNextReason

GetNoNextReason returns the reason why there's no next record (valid when HasNext is false)

func (RecordCursorResult[T]) GetValue

func (r RecordCursorResult[T]) GetValue() T

GetValue returns the value. Panics if HasNext() is false — callers must check HasNext() first. This matches Java's behavior of throwing IllegalResultValueAccessException.

func (RecordCursorResult[T]) HasNext

func (r RecordCursorResult[T]) HasNext() bool

HasNext returns true if this result contains a value

func (RecordCursorResult[T]) HasStoppedBeforeEnd

func (r RecordCursorResult[T]) HasStoppedBeforeEnd() bool

HasStoppedBeforeEnd returns true if the cursor stopped before exhausting all records. This means the cursor can be resumed with the continuation to get more results. Matches Java's RecordCursorResult.hasStoppedBeforeEnd() which checks the continuation, not the reason — with the EndContinuation↔SourceExhausted invariant, these are equivalent.

func (RecordCursorResult[T]) WithContinuation

func (r RecordCursorResult[T]) WithContinuation(continuation RecordCursorContinuation) RecordCursorResult[T]

WithContinuation returns a copy of this result with a different continuation. Matches Java's RecordCursorResult.withContinuation().

type RecordDeserializationError

type RecordDeserializationError struct {
	PrimaryKey any // tuple.Tuple, but using any to avoid import cycle
	Cause      error
}

RecordDeserializationError is returned when a record fails to deserialize (unmarshal) from protobuf. Matches Java's com.apple.foundationdb.record.provider.foundationdb.RecordDeserializationException.

func (*RecordDeserializationError) Error

func (*RecordDeserializationError) Unwrap

func (e *RecordDeserializationError) Unwrap() error

type RecordDoesNotExistError

type RecordDoesNotExistError struct {
	Message    string
	PrimaryKey any // tuple.Tuple, but using any to avoid import cycle
}

RecordDoesNotExistError is returned when attempting to update a record that does not exist. Includes structured context matching Java's RecordDoesNotExistException.

Java equivalent: com.apple.foundationdb.record.provider.foundationdb.RecordDoesNotExistException Location: fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/provider/foundationdb/RecordDoesNotExistException.java Java includes: LogMessageKeys.PRIMARY_KEY

func (*RecordDoesNotExistError) Error

func (e *RecordDoesNotExistError) Error() string

type RecordExistenceCheck

type RecordExistenceCheck int

RecordExistenceCheck controls record existence validation during save operations. Matches Java's FDBRecordStoreBase.RecordExistenceCheck enum.

Java Reference: com.apple.foundationdb.record.provider.foundationdb.FDBRecordStoreBase.RecordExistenceCheck Location: fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/provider/foundationdb/FDBRecordStoreBase.java:394

const (
	// RecordExistenceCheckNone performs no existence validation.
	// This is the default behavior for SaveRecord.
	//
	// Java equivalent: NONE
	RecordExistenceCheckNone RecordExistenceCheck = iota

	// RecordExistenceCheckErrorIfExists throws an error if the record already exists.
	// This corresponds to InsertRecord behavior.
	//
	// Returns: RecordAlreadyExistsError if record exists
	// Java equivalent: ERROR_IF_EXISTS
	RecordExistenceCheckErrorIfExists

	// RecordExistenceCheckErrorIfNotExists throws an error if the record does not exist.
	// Use this for update-only operations where the record must pre-exist.
	//
	// Returns: RecordDoesNotExistError if record doesn't exist
	// Java equivalent: ERROR_IF_NOT_EXISTS
	RecordExistenceCheckErrorIfNotExists

	// RecordExistenceCheckErrorIfTypeChanged throws an error if an existing record has a different type.
	// Use this to prevent accidentally overwriting a record of a different type with the same primary key.
	//
	// Returns: RecordTypeChangedError if existing record has different type
	// Java equivalent: ERROR_IF_RECORD_TYPE_CHANGED
	RecordExistenceCheckErrorIfTypeChanged

	// RecordExistenceCheckErrorIfNotExistsOrTypeChanged combines ERROR_IF_NOT_EXISTS and ERROR_IF_RECORD_TYPE_CHANGED.
	// This corresponds to UpdateRecord behavior - the record must exist and must have the same type.
	//
	// Returns: RecordDoesNotExistError if record doesn't exist
	// Returns: RecordTypeChangedError if existing record has different type
	// Java equivalent: ERROR_IF_NOT_EXISTS_OR_RECORD_TYPE_CHANGED
	RecordExistenceCheckErrorIfNotExistsOrTypeChanged
)

func (RecordExistenceCheck) ErrorIfExists

func (c RecordExistenceCheck) ErrorIfExists() bool

ErrorIfExists returns true if this check should error when a record already exists.

Java equivalent: RecordExistenceCheck.errorIfExists()

func (RecordExistenceCheck) ErrorIfNotExists

func (c RecordExistenceCheck) ErrorIfNotExists() bool

ErrorIfNotExists returns true if this check should error when a record does not exist.

Java equivalent: RecordExistenceCheck.errorIfNotExists()

func (RecordExistenceCheck) ErrorIfTypeChanged

func (c RecordExistenceCheck) ErrorIfTypeChanged() bool

ErrorIfTypeChanged returns true if this check should error when a record's type changes.

Java equivalent: RecordExistenceCheck.errorIfTypeChanged()

func (RecordExistenceCheck) String

func (c RecordExistenceCheck) String() string

String returns a human-readable representation of the existence check.

type RecordIndexUniquenessViolationError

type RecordIndexUniquenessViolationError struct {
	IndexName   string
	IndexKey    tuple.Tuple
	PrimaryKey  tuple.Tuple
	ExistingKey tuple.Tuple
}

RecordIndexUniquenessViolationError indicates a unique index constraint violation. Matches Java's RecordIndexUniquenessViolation.

func (*RecordIndexUniquenessViolationError) Error

type RecordMetaData

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

RecordMetaData describes the schema for records stored in a record store. This is a simplified version for our MVP - just enough to define record types and their primary keys.

func RecordMetaDataFromProto

func RecordMetaDataFromProto(md *gen.MetaData) (*RecordMetaData, error)

RecordMetaDataFromProto deserializes a MetaData proto back into a RecordMetaData. Matches Java's RecordMetaDataBuilder.loadFromProto().

func (*RecordMetaData) CommonPrimaryKey

func (m *RecordMetaData) CommonPrimaryKey() KeyExpression

CommonPrimaryKey returns the primary key expression if all record types share the same one, or nil if they differ. Uses structural comparison via keyExpressionEquals. Matches Java's RecordMetaData.commonPrimaryKey().

func (*RecordMetaData) CommonPrimaryKeyLength

func (m *RecordMetaData) CommonPrimaryKeyLength() int

CommonPrimaryKeyLength returns the number of columns in the primary key if all record types have the same PK length, or -1 if they differ. Matches Java's RecordMetaData.commonPrimaryKeyLength().

func (*RecordMetaData) GetAllIndexes

func (m *RecordMetaData) GetAllIndexes() map[string]*Index

GetAllIndexes returns all indexes by name.

func (*RecordMetaData) GetFormerIndexes

func (m *RecordMetaData) GetFormerIndexes() []*FormerIndex

GetFormerIndexes returns all former (deleted) indexes. Matches Java's RecordMetaData.getFormerIndexes().

func (*RecordMetaData) GetFormerIndexesSince

func (m *RecordMetaData) GetFormerIndexesSince(version int) []*FormerIndex

GetFormerIndexesSince returns former indexes removed since the given version. Matches Java's RecordMetaData.getFormerIndexesSince(int).

func (*RecordMetaData) GetIndex

func (m *RecordMetaData) GetIndex(name string) *Index

GetIndex returns the index with the given name, or nil if not found. Matches Java's RecordMetaData.getIndex(String).

func (*RecordMetaData) GetIndexFromSubspaceKey

func (m *RecordMetaData) GetIndexFromSubspaceKey(key any) *Index

GetIndexFromSubspaceKey returns the index with the given subspace key, or nil. Matches Java's RecordMetaData.getIndexFromSubspaceKey().

func (*RecordMetaData) GetIndexesForRecordType

func (m *RecordMetaData) GetIndexesForRecordType(name string) []*Index

GetIndexesForRecordType returns the indexes defined for a specific record type, including both single-type and multi-type indexes. Does NOT include universal indexes — use GetUniversalIndexes() for those. Matches Java's RecordType.getAllIndexes().

func (*RecordMetaData) GetIndexesToBuildSince

func (m *RecordMetaData) GetIndexesToBuildSince(version int) []*Index

GetIndexesToBuildSince returns indexes that were added or modified since the given metadata version. Used by CreateOrOpen to detect new indexes that need to be built when opening an existing store with updated metadata. Matches Java's RecordMetaData.getIndexesToBuildSince(int).

func (*RecordMetaData) GetRecordCountKey

func (m *RecordMetaData) GetRecordCountKey() KeyExpression

GetRecordCountKey returns the key expression used for record counting. Returns nil if counting is disabled.

func (*RecordMetaData) GetRecordType

func (m *RecordMetaData) GetRecordType(name string) *RecordType

GetRecordType returns the record type for the given name

func (*RecordMetaData) GetRecordTypeFromRecordTypeKey

func (m *RecordMetaData) GetRecordTypeFromRecordTypeKey(key any) *RecordType

GetRecordTypeFromRecordTypeKey returns the record type with the given type key. The key is compared after normalizing integer types (int/int32/int64 → int64). Returns nil if no record type matches. Matches Java's RecordMetaData.getRecordTypeFromRecordTypeKey().

func (*RecordMetaData) GetUnionDescriptor

func (m *RecordMetaData) GetUnionDescriptor() protoreflect.MessageDescriptor

GetUnionDescriptor returns the protobuf message descriptor for UnionDescriptor. Returns nil if the schema has no union (single-type schema). Matches Java's RecordMetaData.getUnionDescriptor().

func (*RecordMetaData) GetUnionFieldForRecordType

func (m *RecordMetaData) GetUnionFieldForRecordType(rt *RecordType) protoreflect.FieldDescriptor

GetUnionFieldForRecordType returns the union field descriptor for a record type. Returns nil if the record type has no union field (single-type schema). Matches Java's RecordMetaData.getUnionFieldForRecordType().

func (*RecordMetaData) GetUniversalIndexes

func (m *RecordMetaData) GetUniversalIndexes() []*Index

GetUniversalIndexes returns indexes that apply to all record types.

func (*RecordMetaData) HasIndexes

func (m *RecordMetaData) HasIndexes() bool

HasIndexes returns true if any indexes are defined.

func (*RecordMetaData) IsSplitLongRecords

func (m *RecordMetaData) IsSplitLongRecords() bool

IsSplitLongRecords returns whether records >100KB are split across multiple KV pairs.

func (*RecordMetaData) IsStoreRecordVersions

func (m *RecordMetaData) IsStoreRecordVersions() bool

IsStoreRecordVersions returns whether record versioning is enabled.

func (*RecordMetaData) PrimaryKeyHasRecordTypePrefix

func (m *RecordMetaData) PrimaryKeyHasRecordTypePrefix() bool

PrimaryKeyHasRecordTypePrefix returns true if all record types have a primary key that starts with a RecordTypeKeyExpression. Matches Java's RecordMetaData.primaryKeyHasRecordTypePrefix().

func (*RecordMetaData) RecordTypes

func (m *RecordMetaData) RecordTypes() map[string]*RecordType

RecordTypes returns all record types

func (*RecordMetaData) RecordTypesForIndex

func (m *RecordMetaData) RecordTypesForIndex(idx *Index) []*RecordType

RecordTypesForIndex returns the record types that the given index covers. Universal indexes cover all record types. Type-specific indexes cover only the record types they are associated with. Matches Java's RecordMetaData.recordTypesForIndex(Index).

func (*RecordMetaData) ToProto

func (m *RecordMetaData) ToProto() (*gen.MetaData, error)

ToProto serializes RecordMetaData to its protobuf representation. Matches Java's RecordMetaData.toProto().

func (*RecordMetaData) Version

func (m *RecordMetaData) Version() int

Version returns the metadata version

type RecordMetaDataBuilder

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

RecordMetaDataBuilder provides a builder pattern for creating RecordMetaData This matches the Java RecordMetaDataBuilder pattern

func NewRecordMetaDataBuilder

func NewRecordMetaDataBuilder() *RecordMetaDataBuilder

NewRecordMetaDataBuilder creates a new builder

func (*RecordMetaDataBuilder) AddIndex

func (b *RecordMetaDataBuilder) AddIndex(recordTypeName string, index *Index) *RecordMetaDataBuilder

AddIndex adds a secondary index for a specific record type. Matches Java's RecordMetaDataBuilder.addIndex(String recordType, Index index).

func (*RecordMetaDataBuilder) AddMultiTypeIndex

func (b *RecordMetaDataBuilder) AddMultiTypeIndex(recordTypeNames []string, index *Index) *RecordMetaDataBuilder

AddMultiTypeIndex adds an index spanning multiple record types. If recordTypeNames is nil or empty, treats as universal index. If only one name, adds as single-type index. Matches Java's RecordMetaDataBuilder.addMultiTypeIndex().

func (*RecordMetaDataBuilder) AddUniversalIndex

func (b *RecordMetaDataBuilder) AddUniversalIndex(index *Index) *RecordMetaDataBuilder

AddUniversalIndex adds an index that applies to all record types. Matches Java's RecordMetaDataBuilder.addUniversalIndex(Index index).

func (*RecordMetaDataBuilder) Build

Build creates the final RecordMetaData. Returns an error if any record type has no primary key set. The record types map is copied to prevent the builder from mutating the built metadata.

func (*RecordMetaDataBuilder) EnableCounterBasedSubspaceKeys

func (b *RecordMetaDataBuilder) EnableCounterBasedSubspaceKeys() *RecordMetaDataBuilder

EnableCounterBasedSubspaceKeys switches index subspace keys from name-based (string) to counter-based (int64). Each index added after this call gets an auto-incrementing integer subspace key instead of the index name. Matches Java's RecordMetaDataBuilder.enableCounterBasedSubspaceKeys().

func (*RecordMetaDataBuilder) GetFormerIndexes

func (b *RecordMetaDataBuilder) GetFormerIndexes() []*FormerIndex

GetFormerIndexes returns the builder's former indexes (for testing/inspection).

func (*RecordMetaDataBuilder) GetRecordCountKey

func (b *RecordMetaDataBuilder) GetRecordCountKey() KeyExpression

GetRecordCountKey returns the record count key expression on the builder.

func (*RecordMetaDataBuilder) GetRecordType

func (b *RecordMetaDataBuilder) GetRecordType(name string) *RecordTypeBuilder

GetRecordType returns the record type builder for setting primary keys, etc. Panics with MetaDataError if the record type does not exist, matching Java's RecordMetaDataBuilder.getRecordType() which throws MetaDataException.

func (*RecordMetaDataBuilder) GetRecordTypes

func (b *RecordMetaDataBuilder) GetRecordTypes() map[string]*RecordType

GetRecordTypes returns the record types map on the builder.

func (*RecordMetaDataBuilder) GetVersion

func (b *RecordMetaDataBuilder) GetVersion() int

GetVersion returns the current metadata version on the builder. Matches Java's RecordMetaDataBuilder.getVersion().

func (*RecordMetaDataBuilder) IsSplitLongRecords

func (b *RecordMetaDataBuilder) IsSplitLongRecords() bool

IsSplitLongRecords returns whether split long records is enabled on the builder. Matches Java's RecordMetaDataBuilder.isSplitLongRecords().

func (*RecordMetaDataBuilder) IsStoreRecordVersions

func (b *RecordMetaDataBuilder) IsStoreRecordVersions() bool

IsStoreRecordVersions returns whether record versioning is enabled on the builder. Matches Java's RecordMetaDataBuilder.isStoreRecordVersions().

func (*RecordMetaDataBuilder) RemoveIndex

func (b *RecordMetaDataBuilder) RemoveIndex(indexName string) *RecordMetaDataBuilder

RemoveIndex removes an index by name and records it as a FormerIndex to prevent subspace key reuse. Matches Java's RecordMetaDataBuilder.removeIndex(String).

func (*RecordMetaDataBuilder) SetRecordCountKey

func (b *RecordMetaDataBuilder) SetRecordCountKey(key KeyExpression) *RecordMetaDataBuilder

SetRecordCountKey sets the key expression for partitioning record counts. If set, the store will maintain record counts using FDB atomic ADD mutations. If nil (default), record counting is disabled. Java equivalent: RecordMetaDataBuilder.setRecordCountKey(KeyExpression)

func (*RecordMetaDataBuilder) SetRecords

SetRecords sets the protobuf file descriptor containing record definitions. Uses the default union message name "UnionDescriptor".

func (*RecordMetaDataBuilder) SetRecordsWithUnionName

func (b *RecordMetaDataBuilder) SetRecordsWithUnionName(fd protoreflect.FileDescriptor, unionName string) *RecordMetaDataBuilder

SetRecordsWithUnionName is SetRecords with an explicit union message name. Use this when the proto file's union message is not called "UnionDescriptor" — e.g. schemas that must coexist with another RecordMetaData in the same Go package (gen.*), where duplicate UnionDescriptor symbols would clash. Behaviour is identical to SetRecords in every other respect.

func (*RecordMetaDataBuilder) SetSplitLongRecords

func (b *RecordMetaDataBuilder) SetSplitLongRecords(split bool) *RecordMetaDataBuilder

SetSplitLongRecords enables or disables splitting records >100KB across multiple FDB key-value pairs. Matches Java's RecordMetaDataBuilder.setSplitLongRecords(boolean).

func (*RecordMetaDataBuilder) SetStoreRecordVersions

func (b *RecordMetaDataBuilder) SetStoreRecordVersions(store bool) *RecordMetaDataBuilder

SetStoreRecordVersions enables or disables automatic record versioning. When enabled, each save assigns an FDBRecordVersion to the record. Java equivalent: RecordMetaDataBuilder.setStoreRecordVersions(boolean)

func (*RecordMetaDataBuilder) SetVersion

func (b *RecordMetaDataBuilder) SetVersion(version int) *RecordMetaDataBuilder

SetVersion sets the metadata schema version. This should be bumped when the schema changes for evolution tracking. Matches Java's RecordMetaDataBuilder.setVersion(int).

type RecordSerializationError

type RecordSerializationError struct {
	Cause error
}

RecordSerializationError is returned when a record fails to serialize (marshal) to protobuf. Matches Java's com.apple.foundationdb.record.provider.foundationdb.RecordSerializationException.

func (*RecordSerializationError) Error

func (e *RecordSerializationError) Error() string

func (*RecordSerializationError) Unwrap

func (e *RecordSerializationError) Unwrap() error

type RecordStoreAlreadyExistsError

type RecordStoreAlreadyExistsError struct{}

RecordStoreAlreadyExistsError is returned when attempting to create a store that already exists. Matches Java's com.apple.foundationdb.record.provider.foundationdb.RecordStoreAlreadyExistsException.

func (*RecordStoreAlreadyExistsError) Error

type RecordStoreDoesNotExistError

type RecordStoreDoesNotExistError struct{}

RecordStoreDoesNotExistError is returned when attempting to open a store that does not exist. Matches Java's com.apple.foundationdb.record.provider.foundationdb.RecordStoreDoesNotExistException.

func (*RecordStoreDoesNotExistError) Error

type RecordStoreNoInfoButNotEmptyError

type RecordStoreNoInfoButNotEmptyError struct {
	FirstKey []byte // First key found in the subspace (Java's LogMessageKeys.KEY)
}

RecordStoreNoInfoButNotEmptyError is returned when a store subspace has data but no valid store header (StoreInfoKey). Matches Java's com.apple.foundationdb.record.provider.foundationdb.RecordStoreNoInfoAndNotEmptyException.

func (*RecordStoreNoInfoButNotEmptyError) Error

type RecordStoreState

type RecordStoreState struct {
	StoreHeader *gen.DataStoreInfo
	IndexStates map[string]IndexState
}

RecordStoreState captures the mutable state of a record store at a point in time. Matches Java's RecordStoreState.

type RecordStoreStateNotLoadedError

type RecordStoreStateNotLoadedError struct{}

RecordStoreStateNotLoadedError is returned when store operations are called before the store state has been loaded via Create/Open/CreateOrOpen. Matches Java's com.apple.foundationdb.record.provider.foundationdb.UninitializedRecordStoreException.

func (*RecordStoreStateNotLoadedError) Error

type RecordType

type RecordType struct {
	// Name of the record type (usually the protobuf message name)
	Name string

	// Protobuf message descriptor
	Descriptor protoreflect.MessageDescriptor

	// Primary key definition
	PrimaryKey KeyExpression

	// Since version (for schema evolution)
	SinceVersion int

	// Record type index in union descriptor (for key construction)
	RecordTypeIndex int

	// Union field descriptor for reflection-based access
	UnionFieldDescriptor protoreflect.FieldDescriptor
	// contains filtered or unexported fields
}

RecordType represents a type of record that can be stored

func (*RecordType) GetAllIndexes

func (rt *RecordType) GetAllIndexes() []*Index

GetAllIndexes returns all indexes for this record type (single-type + multi-type). Does not include universal indexes. Matches Java's RecordType.getAllIndexes().

func (*RecordType) GetIndexes

func (rt *RecordType) GetIndexes() []*Index

GetIndexes returns the indexes defined for this record type (single-type only). Does not include multi-type or universal indexes. Matches Java's RecordType.getIndexes().

func (*RecordType) GetMultiTypeIndexes

func (rt *RecordType) GetMultiTypeIndexes() []*Index

GetMultiTypeIndexes returns the multi-type indexes for this record type. Matches Java's RecordType.getMultiTypeIndexes().

func (*RecordType) GetRecordTypeKey

func (rt *RecordType) GetRecordTypeKey() any

GetRecordTypeKey returns the explicit record type key if set, or falls back to the record type index. Matches Java's RecordType.getRecordTypeKey().

func (*RecordType) HasExplicitRecordTypeKey

func (rt *RecordType) HasExplicitRecordTypeKey() bool

HasExplicitRecordTypeKey returns true if the record type key was explicitly set. Matches Java's RecordType.hasExplicitRecordTypeKey().

func (*RecordType) IsSynthetic

func (rt *RecordType) IsSynthetic() bool

IsSynthetic reports whether this is a synthetic record type (one assembled from other records, e.g. a joined type). The Go port does not model synthetic record types — they are out of scope (see CLAUDE.md) — so this is always false. Kept as a method for 1:1 fidelity with Java's RecordType.isSynthetic() so callers (e.g. the typed-records range preset) read identically to the Java algorithm.

func (*RecordType) PrimaryKeyHasRecordTypePrefix

func (rt *RecordType) PrimaryKeyHasRecordTypePrefix() bool

PrimaryKeyHasRecordTypePrefix returns true if this record type's primary key starts with a RecordTypeKeyExpression — i.e. its records live in a contiguous record-type-keyed sub-range of the records space. Matches Java's RecordType.primaryKeyHasRecordTypePrefix().

type RecordTypeBuilder

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

RecordTypeBuilder provides methods to configure a specific record type

func (*RecordTypeBuilder) SetPrimaryKey

func (rtb *RecordTypeBuilder) SetPrimaryKey(keyExpr KeyExpression) *RecordTypeBuilder

SetPrimaryKey sets the primary key expression for this record type

func (*RecordTypeBuilder) SetRecordTypeKey

func (rtb *RecordTypeBuilder) SetRecordTypeKey(key any) *RecordTypeBuilder

SetRecordTypeKey overrides the auto-derived record type key for this record type. By default, the record type index (proto field number order) is used. Matches Java's RecordTypeBuilder.setRecordTypeKey(Key.Evaluated).

type RecordTypeChangedError

type RecordTypeChangedError struct {
	Message      string
	PrimaryKey   any // tuple.Tuple, but using any to avoid import cycle
	ActualType   string
	ExpectedType string
}

RecordTypeChangedError is returned when attempting to update a record but its type has changed. Includes structured context matching Java's RecordTypeChangedException.

Java equivalent: com.apple.foundationdb.record.provider.foundationdb.RecordTypeChangedException Location: fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/provider/foundationdb/RecordTypeChangedException.java Java includes: LogMessageKeys.PRIMARY_KEY, LogMessageKeys.ACTUAL_TYPE, LogMessageKeys.EXPECTED_TYPE

func (*RecordTypeChangedError) Error

func (e *RecordTypeChangedError) Error() string

type RecordTypeKeyExpression

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

RecordTypeKeyExpression represents the special record type key prefix. Matches Java's RecordTypeKeyExpression: evaluates to the record type key (an integer derived from the union descriptor field number).

func RecordTypeKey

func RecordTypeKey() *RecordTypeKeyExpression

RecordTypeKey creates a key expression that prefixes with the record type

func (*RecordTypeKeyExpression) ColumnSize

func (r *RecordTypeKeyExpression) ColumnSize() int

ColumnSize returns 1 for the type key itself, plus the nested expression's column size if present.

func (*RecordTypeKeyExpression) Evaluate

func (r *RecordTypeKeyExpression) Evaluate(record *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

Evaluate returns the record type key (integer), optionally followed by nested values. Matches Java's RecordTypeKeyExpression.evaluateMessage() which returns record.getRecordType().getRecordTypeKey() — the union descriptor field number.

func (*RecordTypeKeyExpression) EvaluateFlat

func (r *RecordTypeKeyExpression) EvaluateFlat(record *FDBStoredRecord[proto.Message], msg proto.Message) ([]any, error)

EvaluateFlat returns the type key as a single-element []any.

func (*RecordTypeKeyExpression) EvaluateScalar

func (r *RecordTypeKeyExpression) EvaluateScalar(record *FDBStoredRecord[proto.Message], msg proto.Message) (any, error)

EvaluateScalar returns the type key directly — zero alloc.

func (*RecordTypeKeyExpression) FieldNames

func (r *RecordTypeKeyExpression) FieldNames() []string

FieldNames returns the field names accessed by nested expression

func (*RecordTypeKeyExpression) Nest

Nest adds a nested key expression after the record type prefix

func (*RecordTypeKeyExpression) PackDirect

PackDirect encodes the record type key directly into a Packer.

func (*RecordTypeKeyExpression) ToKeyExpression

func (r *RecordTypeKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes a RecordTypeKeyExpression to proto. A bare RecordTypeKeyExpression serializes as RecordTypeKey{}. With a nested expression, serializes as Then{RecordTypeKey{}, nested} matching Java's concat(recordTypeKey(), nested).

type SPFreshConfig

type SPFreshConfig struct {
	NumDimensions int
	Metric        VectorMetric
	Lmax          int     // posting split threshold (entries)
	LminRatio     int     // Lmin = Lmax / LminRatio (merge threshold)
	CellTarget    int     // fine centroids per cell, build target
	CellMax       int     // coarse-split threshold (fine centroids)
	Replication   int     // closure replication cap r
	Alpha         float64 // RNG closure threshold (> 1.0)
	Kn            int     // NPA reassignment neighborhood
	CooldownSec   int     // post-split merge cooldown
	NumExBits     int     // RaBitQ extended bits for posting residual codes
	Sidecar       bool    // fp16 sidecar for re-rank
	// BuildAssignCells is the bulk-build wave-B assignment width w_b (RFC-099):
	// nearest coarse cells whose fines are candidates per imported vector.
	BuildAssignCells int
}

SPFreshConfig is the structural configuration of an SPFresh index. Every field here is immutable for an existing index (RFC-094 §10).

func DefaultSPFreshConfig

func DefaultSPFreshConfig(numDimensions int) SPFreshConfig

DefaultSPFreshConfig returns the RFC-094 defaults for the given dimensionality.

func (SPFreshConfig) Lmin

func (c SPFreshConfig) Lmin() int

Lmin returns the merge threshold in entries.

type SPFreshIntegrityReport

type SPFreshIntegrityReport struct {
	Members                int            // total membership rows in the index
	Sampled                int            // pks actually checked
	OK                     int            // sampled pks whose every membership target holds the posting entry
	MembershipWithoutEntry int            // sampled pks with >=1 membership target missing its posting entry
	TargetStates           map[string]int // membership-target references by centroid state: active/sealed/forward/dead/absent
	BadTargets             int            // target references in forward/dead/absent state (unambiguously bad post-drain)

	// Posting-size accounting (SPANN §3.2.1 balanced-postings / SPFresh LIRE
	// split-merge bounds). The papers' defining property is length-limited
	// postings; LIRE's split exists to hold the ceiling. Post-drain the normal
	// envelope is mostly <=Lmax with some <=4*Lmax (just-split children,
	// unsampled Lmax..2Lmax postings, closure overcount), and NEVER >4*Lmax —
	// the chunked-drain hard guarantee. A split that fails to drain grows a
	// posting unboundedly past the envelope, which OversizedHard catches.
	ActiveFines   int // ACTIVE fine centroids scanned
	Oversized     int // ACTIVE postings with > Lmax entries (soft: includes the legitimate <=4Lmax band)
	OversizedHard int // ACTIVE postings with > 4*Lmax entries (the LIRE hard-envelope violation)
	MaxPostingLen int // largest ACTIVE posting observed

	Violations []SPFreshIntegrityViolation
}

SPFreshIntegrityReport is the structured result of SPFreshCheckIntegrity — the same membership⊆postings + target-state invariants SPFreshDebugIntegrity formats as a string, returned as data for programmatic assertions. The report is descriptive; the caller sets policy. After the maintenance queue is drained to quiescence the strict invariant is MembershipWithoutEntry == 0, BadTargets == 0, and OversizedHard == 0 (every membership target ACTIVE-or- SEALED with its posting entry present, no posting over the 4×Lmax envelope). SEALED targets are valid — sealed postings are still searched mid-split; only FORWARD/DEAD/absent count as BadTargets.

func SPFreshCheckIntegrity

func SPFreshCheckIntegrity(rtx *FDBRecordContext, store *FDBRecordStore, indexName string, sample int) (SPFreshIntegrityReport, error)

SPFreshCheckIntegrity samples up to `sample` pks evenly from the index's own membership rows and verifies, for each, that every membership target holds the pk's posting entry (membership ⊆ postings) and classifies the target centroid's lifecycle state. It is the structured, programmatic form of SPFreshDebugIntegrity. O(index) reads (it streams the membership keyspace) — never call it on a serving path. `sample` <= 0 checks a single pk.

Violations beyond a small cap are counted but not individually recorded (BadTargets / MembershipWithoutEntry stay exact; Violations is truncated).

type SPFreshIntegrityViolation

type SPFreshIntegrityViolation struct {
	PrimaryKey tuple.Tuple
	FineID     int64
	// Kind: "missing_posting" (membership target lacks this pk's posting
	// entry), "absent_target" (target fineID is in no cell), "forward_target"
	// (target centroid split away), "dead_target" (target centroid GC'd).
	Kind string
}

SPFreshIntegrityViolation is one structural defect found by SPFreshCheckIntegrity: a membership row referencing a posting/centroid that the LIRE invariants forbid.

func (SPFreshIntegrityViolation) String

func (v SPFreshIntegrityViolation) String() string

type SPFreshMaintenanceOptions

type SPFreshMaintenanceOptions struct {
	// Tenants is the set of (store, index) pairs to maintain. The caller owns
	// discovery — store layout is application keyspace, not enumerable from
	// inside the record layer. Sharding the list across workers is safe:
	// SweepSPFreshIndexes is concurrent-safe by construction (unique lease
	// owners, task-level exclusion).
	Tenants []SPFreshTenant

	// SweepInterval is the rebalance cadence. <= 0 uses the default (10s).
	SweepInterval time.Duration
	// RefineInterval is the refinement cadence. <= 0 uses the default (5m).
	// Ignored when DisableRefine is set.
	RefineInterval time.Duration
	// DisableRefine turns off the RFC-104 refinement loop entirely (sweep
	// only) — e.g. for a read-mostly fleet where ingest drift never builds up.
	DisableRefine bool

	// Sweep / Refine carry the per-pass budgets and the StoreTimer that
	// accumulates instrumentation (per-kind action counts, lease skips,
	// refine moves/converged — see spfresh_metrics.go). Their zero values are
	// the documented defaults; set Timer to scrape metrics.
	Sweep  SPFreshSweepOptions
	Refine SPFreshRefineOptions

	// OnSweep / OnRefine, when set, are called after each pass with its result
	// and joined per-tenant error — the hook for logging / exporting metrics /
	// alerting on backlog. A pass error is never fatal to the loop (per-tenant
	// failures are already isolated inside Sweep/Refine); the loop runs until
	// ctx is canceled.
	OnSweep  func(SPFreshSweepResult, error)
	OnRefine func(SPFreshRefineResult, error)
}

SPFreshMaintenanceOptions configures the reference maintenance loop.

type SPFreshRecallReport

type SPFreshRecallReport struct {
	K               int     // neighbors per query
	CorpusSize      int     // indexed records scanned for ground truth
	QueriesRun      int     // query samples evaluated
	MeanRecall      float64 // average recall@k across queries (the headline signal)
	MinRecall       float64 // worst single-query recall@k
	PerfectFraction float64 // fraction of queries with recall@k == 1.0
}

SPFreshRecallReport summarizes a recall measurement.

func MeasureSPFreshRecall

func MeasureSPFreshRecall(ctx context.Context, store *FDBRecordStore, indexName string, k, querySamples int, seed int64) (SPFreshRecallReport, error)

MeasureSPFreshRecall measures recall@k of a readable SPFresh index against brute-force ground truth over `querySamples` query vectors drawn from the index's own records (deterministic by seed). Returns a zero-query report when the index is empty. The store must be bound to a transaction (call inside db.Run); the whole scan+queries run in that one tx, so keep the corpus under spfreshMaxRecallCorpus (see its doc for the scale limit). Mostly read-only, but it can inherit SearchSPFreshIndex's read-path split-repair write for any over-envelope posting (none on a maintained index). Distances use the index's configured metric, so the ground-truth ranking matches what the index optimizes, and recall is scored with the SPANN §4.2.1 tie correction (a result within the k-th true distance counts, so equidistant/duplicate vectors don't under-report).

Queries are drawn from the corpus itself (not a held-out set as in the SPANN SIFT benchmark), so absolute numbers run slightly optimistic — the self-match is a guaranteed hit. That is fine for the intended use as a relative drift signal: alert on MeanRecall falling below YOUR measured baseline, not on an absolute target.

type SPFreshRefineOptions

type SPFreshRefineOptions struct {
	// BudgetPerTenant bounds the vectors re-evaluated per tenant per pass.
	// 0 means the default (spfreshRefineFleetBudget).
	BudgetPerTenant int

	// Timer, when non-nil, accumulates refinement instrumentation across the pass
	// (CountSPFreshRefineMoves, CountSPFreshRefineConverged) — the observability
	// the rebalance sweeper gets via its own Timer. Nil disables recording.
	Timer *StoreTimer
}

SPFreshRefineOptions tunes one fleet refinement pass.

type SPFreshRefineResult

type SPFreshRefineResult struct {
	Moves     int // vectors moved (re-routed) across all tenants this pass
	Refined   int // tenants that completed a refine pass without error
	Converged int // tenants whose cursor wrapped a full cycle moving nothing
}

SPFreshRefineResult summarizes one fleet refinement pass.

func RefineSPFreshIndexes

func RefineSPFreshIndexes(ctx context.Context, db *FDBDatabase, tenants []SPFreshTenant, opts SPFreshRefineOptions) (SPFreshRefineResult, error)

RefineSPFreshIndexes runs ONE budgeted refinement pass over each tenant — the "refinement loop beside the rebalancer loop" (RFC-104). Unlike SweepSPFreshIndexes (task-driven: tenants with no pending lifecycle task rows are skipped), refinement is CURSOR-driven and unconditional — every tenant's persistent round-robin cursor advances by up to BudgetPerTenant vectors, re-routing each against the current (converged) topology and moving the stale ones, recovering the closure replication fast ingest never fired.

Run it on a SLOWER cadence than the rebalance sweep: refinement is recall-recovery, not correctness, and a fully converged tenant re-scans its cursor for zero moves each pass. The result's Converged count (cursor wrapped a full cycle with zero moves) lets a caller back off quiescent tenants. As in SweepSPFreshIndexes, per-tenant failures are isolated (joined, not fatal — one corrupt tenant must not halt fleet refinement) and ctx cancellation ends the pass between tenants.

type SPFreshSweepOptions

type SPFreshSweepOptions struct {
	// MaxRoundsPerTenant bounds the scan-and-act rounds per tenant per
	// pass. 0 means the default (8).
	MaxRoundsPerTenant int
	// MaxActionsPerTenant is the per-tenant fairness budget: at most this
	// many lifecycle actions per pass, ENFORCED WITHIN a round too — a
	// whale tenant whose single scan finds thousands of independent task
	// rows must not monopolize the pass. Undrained tenants
	// are reported, not errored — the next pass continues them. 0 means
	// the default (64).
	MaxActionsPerTenant int

	// Timer collects SPFresh maintenance instrumentation (per-kind action
	// counts, zombie cleanups, lease skips — see spfresh_metrics.go) across
	// the pass. Nil disables recording.
	Timer *StoreTimer
}

SPFreshSweepOptions tunes one sweep pass.

type SPFreshSweepResult

type SPFreshSweepResult struct {
	Actions   int // lifecycle actions executed across all tenants
	Worked    int // tenants that had pending maintenance
	Undrained int // tenants whose budget ran out with work remaining
}

SPFreshSweepResult summarizes one sweep pass.

func SweepSPFreshIndexes

func SweepSPFreshIndexes(ctx context.Context, db *FDBDatabase, tenants []SPFreshTenant, opts SPFreshSweepOptions) (SPFreshSweepResult, error)

SweepSPFreshIndexes makes ONE bounded pass over the tenants: a cheap pending-work probe per tenant (two snapshot reads), then a round-budgeted rebalance for the tenants that need it. Per-tenant failures are collected, not fatal — one corrupt tenant must not halt fleet maintenance; the pass continues and the joined error reports every failure. Callers loop passes on their own cadence and stop idling tenants however they like (the result says whether anything happened).

type SPFreshTenant

type SPFreshTenant struct {
	StoreBuilder func(*FDBRecordContext) (*FDBRecordStore, error)
	IndexName    string
}

SPFreshTenant names one index a sweeper drives: the store (the caller owns tenant discovery — store layout is application keyspace, not enumerable from inside the record layer) and the index within it.

type ScalarEvaluator

type ScalarEvaluator interface {
	EvaluateScalar(record *FDBStoredRecord[proto.Message], msg proto.Message) (any, error)
}

ScalarEvaluator is an optional interface for KeyExpressions that extract a single scalar value. Avoids both the outer [][]any and inner []any allocs.

type ScanLimitReachedError

type ScanLimitReachedError struct {
	// Reason is the out-of-band stop reason that triggered the failure
	// (ScanLimitReached or ByteLimitReached).
	Reason NoNextReason
}

ScanLimitReachedError is returned by a leaf cursor when it hits a scanned-records or scanned-bytes limit AND ExecuteProperties. FailOnScanLimitReached is set. Mirrors Java's ScanLimitReachedException (RecordCoreException, SQLSTATE 54F01): with setFailOnScanLimitReached(true) the scan errors instead of paginating. Default (false) is unchanged — the cursor returns a ScanLimitReached/ByteLimitReached NoNextReason and the caller paginates via the continuation.

func (*ScanLimitReachedError) Error

func (e *ScanLimitReachedError) Error() string

type ScanProperties

type ScanProperties struct {
	// ExecuteProperties holds the execution-level properties
	ExecuteProperties ExecuteProperties

	// Reverse indicates if the scan should be in reverse order
	Reverse bool

	// CursorStreamingMode overrides the default streaming mode
	CursorStreamingMode CursorStreamingMode
}

ScanProperties groups properties that pertain to a single scan

func ForwardScan

func ForwardScan() ScanProperties

ForwardScan returns properties for a forward scan with default execution properties. Returns a fresh copy each time to prevent mutation of shared state.

func NewScanProperties

func NewScanProperties(executeProps ExecuteProperties) ScanProperties

NewScanProperties creates scan properties with the given execution properties

func ReverseScan

func ReverseScan() ScanProperties

ReverseScan returns properties for a reverse scan with default execution properties. Returns a fresh copy each time to prevent mutation of shared state.

func (ScanProperties) GetExecuteProperties

func (s ScanProperties) GetExecuteProperties() ExecuteProperties

GetExecuteProperties returns the execute properties

func (ScanProperties) IsReverse

func (s ScanProperties) IsReverse() bool

IsReverse returns true if this is a reverse scan

func (ScanProperties) WithExecuteProperties

func (s ScanProperties) WithExecuteProperties(props ExecuteProperties) ScanProperties

WithExecuteProperties returns a copy with the specified execute properties

func (ScanProperties) WithReverse

func (s ScanProperties) WithReverse(reverse bool) ScanProperties

WithReverse returns a copy with the reverse flag set

func (ScanProperties) WithStreamingMode

func (s ScanProperties) WithStreamingMode(mode CursorStreamingMode) ScanProperties

WithStreamingMode returns a copy with the specified streaming mode

type SplitKeyExpression

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

SplitKeyExpression takes a key expression producing multiple single-element results (via FanOut) and splits them into fixed-size batches. Each batch concatenates splitSize values into one tuple. For example, 12 values with splitSize 3 produces 4 tuples of 3 elements each.

The joined expression must have column size 1 and must create duplicates (e.g. FanOut on a repeated field). The total number of values must be an even multiple of splitSize.

Matches Java's com.apple.foundationdb.record.metadata.expressions.SplitKeyExpression.

func Split

func Split(joined KeyExpression, splitSize int) *SplitKeyExpression

Split creates a SplitKeyExpression that batches the joined expression's results into groups of splitSize. splitSize must be > 0.

func (*SplitKeyExpression) ColumnSize

func (s *SplitKeyExpression) ColumnSize() int

ColumnSize returns the split size — each batch produces splitSize columns. Matches Java's SplitKeyExpression.getColumnSize().

func (*SplitKeyExpression) Evaluate

func (s *SplitKeyExpression) Evaluate(record *FDBStoredRecord[proto.Message], msg proto.Message) ([][]any, error)

Evaluate evaluates the joined expression and splits the results into batches of splitSize. Each result from the joined expression must be a single-element tuple (from FanOut). The values are flattened, then chunked.

Returns an error if the total number of values is not evenly divisible by splitSize, matching Java's RecordCoreException behavior.

func (*SplitKeyExpression) FieldNames

func (s *SplitKeyExpression) FieldNames() []string

FieldNames returns the field names accessed by the joined expression.

func (*SplitKeyExpression) GetJoined

func (s *SplitKeyExpression) GetJoined() KeyExpression

GetJoined returns the underlying joined key expression.

func (*SplitKeyExpression) GetSplitSize

func (s *SplitKeyExpression) GetSplitSize() int

GetSplitSize returns the number of elements per batch.

func (*SplitKeyExpression) ToKeyExpression

func (s *SplitKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes SplitKeyExpression to proto. Matches Java's SplitKeyExpression.toKeyExpression().

type StaleMetaDataVersionError

type StaleMetaDataVersionError struct {
	LocalVersion  int
	StoredVersion int
}

StaleMetaDataVersionError is returned when the stored metadata version is newer than the local metadata version, meaning another instance already evolved the schema. Matches Java's RecordStoreStaleMetaDataVersionException.

func (*StaleMetaDataVersionError) Error

func (e *StaleMetaDataVersionError) Error() string

type StartContinuation

type StartContinuation struct{}

StartContinuation represents the start of a cursor's iteration, or a state where no continuation is available for the current result. Unlike EndContinuation, this is NOT terminal — the cursor may have more data. Matches Java's RecordCursorStartContinuation.

func (*StartContinuation) IsEnd

func (c *StartContinuation) IsEnd() bool

IsEnd returns false — StartContinuation is never an end state.

func (*StartContinuation) ToBytes

func (c *StartContinuation) ToBytes() ([]byte, error)

ToBytes returns nil (no position information available).

type StoreBuilder

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

StoreBuilder builds an FDBRecordStore with configuration options. This follows the builder pattern from Java exactly.

func NewStoreBuilder

func NewStoreBuilder() *StoreBuilder

NewStoreBuilder creates a new store builder

func (*StoreBuilder) Build

func (b *StoreBuilder) Build() (*FDBRecordStore, error)

Build returns a store without checking database state (advanced use case)

func (*StoreBuilder) Create

func (b *StoreBuilder) Create() (*FDBRecordStore, error)

Create creates a new record store, fails if store already exists

func (*StoreBuilder) CreateOrOpen

func (b *StoreBuilder) CreateOrOpen() (*FDBRecordStore, error)

CreateOrOpen creates store if it doesn't exist, opens if it does (like Java). When opening an existing store whose metadata version is older than the current metadata, new indexes are automatically rebuilt inline. Matches Java's FDBRecordStore.checkPossiblyRebuild().

func (*StoreBuilder) Open

func (b *StoreBuilder) Open() (*FDBRecordStore, error)

Open opens an existing record store, fails if store doesn't exist. When the current metadata version is higher than the stored version, new indexes are automatically rebuilt inline (matching Java's checkVersion flow).

func (*StoreBuilder) SetAssumeAllIndexesReadable

func (b *StoreBuilder) SetAssumeAllIndexesReadable(assume bool) *StoreBuilder

SetAssumeAllIndexesReadable pre-populates an empty indexStates map during Build(), making ensureStoreStateLoaded() a complete no-op (zero FDB reads, zero lazy-load). Safe when CreateOrOpen ran at startup and all indexes are known to be READABLE. This is an explicit opt-in for maximum performance in the Build() path.

func (*StoreBuilder) SetBypassFullStoreLockReason

func (b *StoreBuilder) SetBypassFullStoreLockReason(reason string) *StoreBuilder

SetBypassFullStoreLockReason sets a reason string that, if it matches the stored FULL_STORE lock reason exactly, allows the store to be opened despite the lock. This is intended for recovery operations. Calling it with "" bypasses a lock whose stored reason is empty — Java's bypass is a @Nullable String compared with equals(), so the empty string is a valid bypass value, distinct from "no bypass" (the field's nil default). Matches Java's FDBRecordStore.Builder.setBypassFullStoreLockReason().

func (*StoreBuilder) SetContext

func (b *StoreBuilder) SetContext(ctx *FDBRecordContext) *StoreBuilder

SetContext sets the record context

func (*StoreBuilder) SetDatabase

func (b *StoreBuilder) SetDatabase(db *FDBDatabase) *StoreBuilder

SetDatabase sets the database for inheriting the store state cache. Matches Java's FDBRecordStore.Builder.setDatabase().

func (*StoreBuilder) SetIndexRebuildPolicy

func (b *StoreBuilder) SetIndexRebuildPolicy(policy IndexRebuildPolicy) *StoreBuilder

SetIndexRebuildPolicy sets the policy for rebuilding indexes during store open when the metadata version changes. If not set, DefaultIndexRebuildPolicy is used (inline rebuild for ≤200 records, DISABLED otherwise). Matches Java's FDBRecordStore.newBuilder().setUserVersionChecker().

func (*StoreBuilder) SetMetaDataProvider

func (b *StoreBuilder) SetMetaDataProvider(metaData *RecordMetaData) *StoreBuilder

SetMetaDataProvider sets the metadata

func (*StoreBuilder) SetSkipPossiblyRebuild

func (b *StoreBuilder) SetSkipPossiblyRebuild(skip bool) *StoreBuilder

SetSkipPossiblyRebuild disables automatic index rebuild checks during Open/CreateOrOpen. When set, the store will not call checkPossiblyRebuild even if the metadata version changed. This is used by OnlineIndexer which manages index states independently. Matches Java's IndexMaintenanceFilter.NONE behavior.

func (*StoreBuilder) SetStoreStateCache

func (b *StoreBuilder) SetStoreStateCache(cache FDBRecordStoreStateCache) *StoreBuilder

SetStoreStateCache sets a per-store cache override. If not set, the database's cache is used. Matches Java's FDBRecordStore.Builder.setStoreStateCache().

func (*StoreBuilder) SetSubspace

func (b *StoreBuilder) SetSubspace(subspace subspace.Subspace) *StoreBuilder

SetSubspace sets the subspace for this store

type StoreExistenceCheck

type StoreExistenceCheck int

StoreExistenceCheck controls how store existence is validated during open. Matches Java's FDBRecordStoreBase.StoreExistenceCheck.

const (
	// ExistenceCheckNone performs no existence check.
	ExistenceCheckNone StoreExistenceCheck = iota
	// ExistenceCheckErrorIfExists fails if the store already exists.
	ExistenceCheckErrorIfExists
	// ExistenceCheckErrorIfNotExists fails if the store does not exist.
	ExistenceCheckErrorIfNotExists
)

type StoreIsFullyLockedError

type StoreIsFullyLockedError struct {
	Reason    string
	Timestamp int64
}

StoreIsFullyLockedError is returned when attempting to open a store with FULL_STORE lock state without providing the correct bypass reason. Matches Java's com.apple.foundationdb.record.StoreIsFullyLockedException.

func (*StoreIsFullyLockedError) Error

func (e *StoreIsFullyLockedError) Error() string

type StoreIsLockedForRecordUpdatesError

type StoreIsLockedForRecordUpdatesError struct {
	Reason    string
	Timestamp int64
}

StoreIsLockedForRecordUpdatesError is returned when attempting to modify records in a store with FORBID_RECORD_UPDATE lock state. Matches Java's com.apple.foundationdb.record.StoreIsLockedForRecordUpdates.

func (*StoreIsLockedForRecordUpdatesError) Error

type StoreRecordFunction

type StoreRecordFunction struct {
	Name string
}

StoreRecordFunction identifies a function to be evaluated on a record using store context (not index-backed). Matches Java's com.apple.foundationdb.record.metadata.StoreRecordFunction.

type StoreTimer

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

StoreTimer collects instrumentation counters for Record Layer operations. All operations are goroutine-safe. A nil *StoreTimer is safe to use (all methods are no-ops on nil receiver).

func NewStoreTimer

func NewStoreTimer() *StoreTimer

NewStoreTimer creates a new StoreTimer.

func (*StoreTimer) GetCount

func (t *StoreTimer) GetCount(event Event) int64

GetCount returns the occurrence count for the given event (0 if never recorded).

func (*StoreTimer) GetCounter

func (t *StoreTimer) GetCounter(event Event) *Counter

GetCounter returns the counter for the given event, or nil if never recorded.

func (*StoreTimer) GetTimeNanos

func (t *StoreTimer) GetTimeNanos(event Event) int64

GetTimeNanos returns the cumulative nanoseconds for the given event (0 if never recorded).

func (*StoreTimer) Increment

func (t *StoreTimer) Increment(event Event)

Increment increments the event's count and cumulative value by 1.

func (*StoreTimer) IncrementBy

func (t *StoreTimer) IncrementBy(event Event, amount int64)

IncrementBy increments the event's count and cumulative value by amount.

func (*StoreTimer) Record

func (t *StoreTimer) Record(event Event, timeNanos int64)

Record records an elapsed time in nanoseconds for the given event.

func (*StoreTimer) RecordSince

func (t *StoreTimer) RecordSince(event Event, startTime time.Time)

RecordSince records the duration elapsed since startTime for the given event.

func (*StoreTimer) Reset

func (t *StoreTimer) Reset()

Reset clears all counters from the timer.

func (*StoreTimer) Snapshot

func (t *StoreTimer) Snapshot() map[string]*CounterSnapshot

Snapshot returns an immutable snapshot of all counters at the current instant. The returned map is keyed by Event.Name.

type SubspaceSplitter

type SubspaceSplitter interface {
	SubspaceOf(keyBytes []byte) (subspace.Subspace, error)
	SubspaceTag(ss subspace.Subspace) (tuple.Tuple, error)
}

SubspaceSplitter determines which sub-map a given FDB key belongs to. Used by BunchedMapMultiIterator to partition scans across multiple BunchedMaps. Matches Java's com.apple.foundationdb.map.SubspaceSplitter.

type SynchronizedSessionLockedError

type SynchronizedSessionLockedError struct {
	ExistingIndexerID string
	ExistingInfo      string
	HeartbeatAgeMs    int64
	LeaseLengthMs     int64
}

SynchronizedSessionLockedError is returned when a non-mutual indexer detects an active heartbeat from another indexer process. Matches Java's SynchronizedSessionLockedException.

func (*SynchronizedSessionLockedError) Error

type TakeoverType

type TakeoverType int

TakeoverType represents allowed build method conversions when resuming an index build that was started by a different indexing method. Matches Java's OnlineIndexer.IndexingPolicy.TakeoverTypes.

const (
	// TakeoverMultiTargetToSingle allows a single-target BY_RECORDS build to continue
	// a MULTI_TARGET_BY_RECORDS build.
	TakeoverMultiTargetToSingle TakeoverType = iota
	// TakeoverMutualToSingle allows a single-target BY_RECORDS build to continue
	// a MUTUAL_BY_RECORDS build.
	TakeoverMutualToSingle
	// TakeoverByRecordsToMutual allows a MUTUAL_BY_RECORDS build to continue
	// a BY_RECORDS or MULTI_TARGET_BY_RECORDS build.
	TakeoverByRecordsToMutual
)

type TextIndexBunchedSerializer

type TextIndexBunchedSerializer struct{}

TextIndexBunchedSerializer serializes Tuple keys and position lists ([]int) for TEXT indexes. Position lists are delta-compressed using base-128 variable-length integer encoding. Wire-compatible with Java's com.apple.foundationdb.record.provider.foundationdb.indexes.TextIndexBunchedSerializer.

func TextIndexBunchedSerializerInstance

func TextIndexBunchedSerializerInstance() *TextIndexBunchedSerializer

TextIndexBunchedSerializerInstance returns the singleton serializer.

func (*TextIndexBunchedSerializer) CanAppend

func (s *TextIndexBunchedSerializer) CanAppend() bool

CanAppend returns true — this format supports appending entries without re-serialization.

func (*TextIndexBunchedSerializer) DeserializeEntries

func (s *TextIndexBunchedSerializer) DeserializeEntries(key tuple.Tuple, data []byte) ([]BunchedEntry[tuple.Tuple, []int], error)

DeserializeEntries deserializes a bunch of entries from data, using key as the first entry's key. Matches Java's TextIndexBunchedSerializer.deserializeEntries().

func (*TextIndexBunchedSerializer) DeserializeKey

func (s *TextIndexBunchedSerializer) DeserializeKey(data []byte, offset, length int) (tuple.Tuple, error)

DeserializeKey unpacks a Tuple key from data[offset:offset+length]. Matches Java's TextIndexBunchedSerializer.deserializeKey().

func (*TextIndexBunchedSerializer) DeserializeKeys

func (s *TextIndexBunchedSerializer) DeserializeKeys(key tuple.Tuple, data []byte) ([]tuple.Tuple, error)

DeserializeKeys deserializes only the keys from a bunch (skipping values for efficiency). Matches Java's TextIndexBunchedSerializer.deserializeKeys().

func (*TextIndexBunchedSerializer) SerializeEntries

func (s *TextIndexBunchedSerializer) SerializeEntries(entries []BunchedEntry[tuple.Tuple, []int]) ([]byte, error)

SerializeEntries packs an entry list into a single byte array. Format: PREFIX + entries (first entry's key omitted). Matches Java's TextIndexBunchedSerializer.serializeEntries().

func (*TextIndexBunchedSerializer) SerializeEntry

func (s *TextIndexBunchedSerializer) SerializeEntry(key tuple.Tuple, value []int) ([]byte, error)

SerializeEntry packs a single key-value pair (for appending to a bunch). Format: varInt(keyLen) + keyBytes + varInt(listSize) + deltaCompressedList Matches Java's TextIndexBunchedSerializer.serializeEntry().

func (*TextIndexBunchedSerializer) SerializeKey

func (s *TextIndexBunchedSerializer) SerializeKey(key tuple.Tuple) []byte

SerializeKey packs a key using standard Tuple encoding. Matches Java's TextIndexBunchedSerializer.serializeKey().

type TextSubspaceSplitter

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

TextSubspaceSplitter splits TEXT index keys by grouping columns. Given an FDB key in the index subspace, extracts the first groupingColumns elements as the subspace prefix for that token's BunchedMap. Matches Java's TextSubspaceSplitter.

func NewTextSubspaceSplitter

func NewTextSubspaceSplitter(indexSubspace subspace.Subspace, groupingColumns int) *TextSubspaceSplitter

NewTextSubspaceSplitter creates a splitter for TEXT index scans.

func (*TextSubspaceSplitter) SubspaceOf

func (s *TextSubspaceSplitter) SubspaceOf(keyBytes []byte) (subspace.Subspace, error)

SubspaceOf extracts the subspace for a given FDB key by taking the first groupingColumns elements of the unpacked tuple.

func (*TextSubspaceSplitter) SubspaceTag

func (s *TextSubspaceSplitter) SubspaceTag(ss subspace.Subspace) (tuple.Tuple, error)

SubspaceTag returns the grouping key tuple for a subspace.

type TextTokenizer

type TextTokenizer interface {
	// Name returns the tokenizer's name. Matches Java's getName().
	Name() string

	// Tokenize returns an iterator of tokens from the input text.
	// Returns an error if the version is out of bounds.
	// Matches Java's tokenize(String, int, TokenizerMode).
	Tokenize(text string, version int, mode TokenizerMode) (TokenIterator, error)

	// TokenizeToMap returns a map from token to position list (0-indexed).
	// Returns an error if the version is out of bounds.
	// Matches Java's tokenizeToMap(String, int, TokenizerMode).
	TokenizeToMap(text string, version int, mode TokenizerMode) (map[string][]int, error)

	// TokenizeToList returns all tokens as a list.
	// Returns an error if the version is out of bounds.
	// Matches Java's tokenizeToList(String, int, TokenizerMode).
	TokenizeToList(text string, version int, mode TokenizerMode) ([]string, error)

	// MaxVersion returns the maximum supported tokenizer version.
	MaxVersion() int

	// MinVersion returns the minimum supported tokenizer version.
	MinVersion() int
}

TextTokenizer tokenizes text fields for full-text indexes. Matches Java's com.apple.foundationdb.record.provider.common.text.TextTokenizer.

func GetTextTokenizer

func GetTextTokenizer(name string) (TextTokenizer, error)

GetTextTokenizer returns the tokenizer with the given name from the global registry. If name is empty, returns the default tokenizer.

type TextTokenizerFactory

type TextTokenizerFactory interface {
	// Name returns the tokenizer name.
	Name() string
	// GetTokenizer returns a tokenizer instance.
	GetTokenizer() TextTokenizer
}

TextTokenizerFactory creates instances of a TextTokenizer. Matches Java's TextTokenizerFactory.

type TextTokenizerRegistry

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

TextTokenizerRegistry manages TextTokenizer instances by name. Matches Java's TextTokenizerRegistry / TextTokenizerRegistryImpl.

func GlobalTextTokenizerRegistry

func GlobalTextTokenizerRegistry() *TextTokenizerRegistry

GlobalTextTokenizerRegistry returns the singleton tokenizer registry, pre-loaded with the default tokenizer.

func (*TextTokenizerRegistry) GetTokenizer

func (r *TextTokenizerRegistry) GetTokenizer(name string) (TextTokenizer, error)

GetTokenizer returns the tokenizer with the given name. If name is empty, returns the default tokenizer. Returns an error if no tokenizer with that name exists.

func (*TextTokenizerRegistry) Register

func (r *TextTokenizerRegistry) Register(factory TextTokenizerFactory) error

Register adds a tokenizer factory to the registry. Returns an error if a different factory with the same name is already registered.

func (*TextTokenizerRegistry) Reset

func (r *TextTokenizerRegistry) Reset()

Reset clears and reinitializes the registry with only the default tokenizer.

type TimeLimitExceededError

type TimeLimitExceededError struct {
	TimeLimit time.Duration
	Elapsed   time.Duration
}

TimeLimitExceededError is returned when the OnlineIndexer's overall time limit is exceeded. Matches Java's com.apple.foundationdb.record.provider.foundationdb.IndexingBase.TimeLimitException.

func (*TimeLimitExceededError) Error

func (e *TimeLimitExceededError) Error() string

type TimeWindowForFunction

type TimeWindowForFunction struct {
	LeaderboardType      int
	LeaderboardTimestamp int64
}

TimeWindowForFunction specifies a leaderboard time window for record/aggregate functions. Matches Java's com.apple.foundationdb.record.provider.foundationdb.leaderboard.TimeWindowForFunction.

type TimeWindowLeaderboardWindowUpdate

type TimeWindowLeaderboardWindowUpdate struct {
	UpdateTimestamp int64
	HighScoreFirst  bool
	DeleteBefore    int64
	AllTime         bool
	Specs           []TimeWindowSpec
	NLevels         int
	Rebuild         TimeWindowRebuild
}

TimeWindowLeaderboardWindowUpdate is an operation to manage active time windows. Matches Java's TimeWindowLeaderboardWindowUpdate.

type TimeWindowRebuild

type TimeWindowRebuild int

TimeWindowRebuild controls when to rebuild the index after adding windows.

const (
	TimeWindowRebuildNever                TimeWindowRebuild = 0
	TimeWindowRebuildAlways               TimeWindowRebuild = 1
	TimeWindowRebuildIfOverlappingChanged TimeWindowRebuild = 2
)

type TimeWindowSpec

type TimeWindowSpec struct {
	Type           int
	BaseTimestamp  int64
	StartIncrement int64
	Duration       int64
	Count          int
}

TimeWindowSpec defines parameters for creating a batch of time windows. Matches Java's TimeWindowLeaderboardWindowUpdate.TimeWindowSpec.

type TokenIterator

type TokenIterator interface {
	// HasNext returns true if there are more tokens.
	HasNext() bool
	// Next returns the next token. Panics if no more tokens.
	Next() string
}

TokenIterator iterates over tokens produced by a TextTokenizer.

type TokenizerMode

type TokenizerMode int

TokenizerMode controls whether tokenization is for indexing or querying. Some tokenizers may behave differently in each mode (e.g., n-gram tokenizers). Matches Java's TextTokenizer.TokenizerMode.

const (
	// TokenizerModeIndex tokenizes for indexing documents.
	TokenizerModeIndex TokenizerMode = iota
	// TokenizerModeQuery tokenizes for query strings.
	TokenizerModeQuery
)

type TransactionPriority

type TransactionPriority int

TransactionPriority controls the priority of FDB transactions. Matches Java's FDBTransactionPriority.

const (
	// PriorityDefault is the default transaction priority.
	PriorityDefault TransactionPriority = iota
	// PriorityBatch is a lower priority for background/batch operations.
	PriorityBatch
	// PrioritySystemImmediate is the highest priority, bypasses throttling.
	// Use with extreme care — only for system-level operations.
	PrioritySystemImmediate
)

type TransactionSizeExceededError

type TransactionSizeExceededError struct {
	CurrentBytes int64
	LimitBytes   int64
}

TransactionSizeExceededError is returned when the approximate transaction size exceeds the configured error threshold. Callers should commit the current transaction and start a new one.

func (*TransactionSizeExceededError) Error

type TransactionSizeWarningError

type TransactionSizeWarningError struct {
	CurrentBytes int64
	LimitBytes   int64
}

TransactionSizeWarningError is returned once per transaction when the approximate size exceeds the configured warning threshold.

func (*TransactionSizeWarningError) Error

type TupleRange

type TupleRange struct {
	Low          tuple.Tuple
	High         tuple.Tuple
	LowEndpoint  EndpointType
	HighEndpoint EndpointType
}

TupleRange specifies a range of tuples for index scanning. Matches Java's com.apple.foundationdb.record.TupleRange.

func TupleRangeAllOf

func TupleRangeAllOf(prefix tuple.Tuple) TupleRange

TupleRangeAllOf returns a range for all entries with the given tuple prefix. Matches Java's TupleRange.allOf(Tuple). For example, TupleRangeAllOf(tuple.Tuple{"alice"}) returns all index entries where the first indexed value is "alice".

func TupleRangeBetween

func TupleRangeBetween(low, high tuple.Tuple) TupleRange

TupleRangeBetween returns a range [low, high) — low inclusive, high exclusive. Matches Java's TupleRange.between(Tuple, Tuple).

func TupleRangeBetweenInclusive

func TupleRangeBetweenInclusive(low, high tuple.Tuple) TupleRange

TupleRangeBetweenInclusive returns a range [low, high] — both inclusive. Matches Java's TupleRange.betweenInclusive(Tuple, Tuple).

func TupleRangePrefixString

func TupleRangePrefixString(token string) TupleRange

TupleRangePrefixString creates a range scanning all entries whose string element starts with the given prefix. Both endpoints use EndpointTypePrefixString so that the tuple-packed trailing null byte is stripped (low) or strinc'd (high). Matches Java's TupleRange.prefixedBy(String).

func VectorDistanceScanRange

func VectorDistanceScanRange(queryVector []float64, k, efSearch int) TupleRange

VectorDistanceScanRange creates a TupleRange encoding a BY_DISTANCE kNN query. This is the Go equivalent of Java's VectorIndexScanBounds. The query vector, k, and efSearch are encoded into TupleRange fields so they can be passed through the standard ScanIndexByType API.

Usage:

store.ScanIndexByType(index, IndexScanByDistance,
    VectorDistanceScanRange(queryVec, 10, 200),
    nil, ForwardScan)

func VectorDistanceScanRangeOrdered

func VectorDistanceScanRangeOrdered(queryVector []float64, k, efSearch, cRerank int, prefix tuple.Tuple) TupleRange

VectorDistanceScanRangeOrdered builds a BY_DISTANCE scan range for the RFC-156 Phase B distance-ORDERED stream. It DECOUPLES the re-rank budget from the probe width: cRerank (the re-rank budget c) rides the High-tuple's c slot (index 3 of the SPFresh (k, kc, w, c, ε) contract), while efSearch stays the index's TUNED probe width (SPFresh kc=64, HNSW ef) rather than being forced up to the horizon. Threading c directly avoids the efSearch>0 path's 4×k re-rank inflation and kc override (rejected in Phase B review). The intermediate w slot is 0 ("use the index default fine-probe width"). HNSW reads only (k, efSearch) and ignores the extra slots.

Who reads cRerank: ONLY the legacy self-limiting one-shot SPFresh path (ScanByDistance → searchCurrentGeneration, where c bounds the finalize re-rank). The STREAMING ordered path (IndexScanByDistanceOrderedStream → newOrderedStreamCursor) does NOT read slot 3 at all — its re-rank/candidate cap is the demand-driven stream budget (spfreshDefaultStreamCandidateBudget=4000 in defaultSPFreshStreamBudget), NOT this High-tuple slot. So cRerank/slot-3 is currently UNUSED by the streaming path; it is honoured only when this range feeds the one-shot reader, and is otherwise inert (carried for shape symmetry). Kept in the signature so the one-shot path stays expressible without a second builder; do not remove it just because the streaming path ignores it.

func VectorDistanceScanRangeWithPrefix

func VectorDistanceScanRangeWithPrefix(queryVector []float64, k, efSearch int, prefix tuple.Tuple) TupleRange

VectorDistanceScanRangeWithPrefix creates a TupleRange encoding a BY_DISTANCE kNN query scoped to a specific prefix partition. The prefix identifies which independent HNSW graph to search (e.g., a specific group_id value).

Usage:

store.ScanIndexByType(index, IndexScanByDistance,
    VectorDistanceScanRangeWithPrefix(queryVec, 10, 200, tuple.Tuple{int64(42)}),
    nil, ForwardScan)

func (TupleRange) Contains

func (r TupleRange) Contains(t tuple.Tuple) bool

Contains checks if a tuple falls within the range.

func (TupleRange) Prepend

func (r TupleRange) Prepend(prefix tuple.Tuple) TupleRange

Prepend prepends a tuple prefix to both Low and High bounds. Matches Java's TupleRange.prepend(Tuple).

func (TupleRange) ToFDBRange

func (r TupleRange) ToFDBRange(ss subspace.Subspace) fdb.KeyRange

ToFDBRange converts this TupleRange to an fdb.KeyRange relative to a subspace. Matches Java's TupleRange.toRange(Subspace).

type TypedFDBRecordStore

type TypedFDBRecordStore[T proto.Message] struct {
	// contains filtered or unexported fields
}

TypedFDBRecordStore provides type-safe record operations with generics

func GetTypedRecordStore

func GetTypedRecordStore[T proto.Message](store *FDBRecordStore, recordTypeName string) (*TypedFDBRecordStore[T], error)

GetTypedRecordStore creates a type-safe wrapper for a specific record type This follows Java's FDBRecordStore.getTypedRecordStore() pattern

func NewTypedRecordStore

func NewTypedRecordStore[T proto.Message](
	baseStore *FDBRecordStore,
	recordType *RecordType,
	unwrapFunc func(*gen.UnionDescriptor) (T, error),
	wrapFunc func(T) (*gen.UnionDescriptor, error),
) *TypedFDBRecordStore[T]

NewTypedRecordStore creates a new typed record store that wraps the base store

func (*TypedFDBRecordStore[T]) AddRecordReadConflict

func (ts *TypedFDBRecordStore[T]) AddRecordReadConflict(primaryKey tuple.Tuple) error

AddRecordReadConflict adds a read conflict range for the given primary key

func (*TypedFDBRecordStore[T]) AddRecordWriteConflict

func (ts *TypedFDBRecordStore[T]) AddRecordWriteConflict(primaryKey tuple.Tuple) error

AddRecordWriteConflict adds a write conflict range for the given primary key

func (*TypedFDBRecordStore[T]) Context

func (ts *TypedFDBRecordStore[T]) Context() *FDBRecordContext

Context returns the record context this store is using

func (*TypedFDBRecordStore[T]) DeleteAllRecords

func (ts *TypedFDBRecordStore[T]) DeleteAllRecords() error

DeleteAllRecords deletes all records from the store

func (*TypedFDBRecordStore[T]) DeleteRecord

func (ts *TypedFDBRecordStore[T]) DeleteRecord(primaryKey tuple.Tuple) (bool, error)

DeleteRecord deletes a typed record by its primary key

func (*TypedFDBRecordStore[T]) GetRecordCount

func (ts *TypedFDBRecordStore[T]) GetRecordCount() (int64, error)

GetRecordCount returns the total record count

func (*TypedFDBRecordStore[T]) GetSnapshotRecordCount

func (ts *TypedFDBRecordStore[T]) GetSnapshotRecordCount(countKey tuple.Tuple) (int64, error)

GetSnapshotRecordCount returns the count for a specific count key

func (*TypedFDBRecordStore[T]) InsertRecord

func (ts *TypedFDBRecordStore[T]) InsertRecord(record T) (*FDBStoredRecord[T], error)

InsertRecord saves a typed record and throws an error if it already exists

func (*TypedFDBRecordStore[T]) LoadRecord

func (ts *TypedFDBRecordStore[T]) LoadRecord(primaryKey tuple.Tuple) (*FDBStoredRecord[T], error)

LoadRecord loads a record by its primary key with compile-time type safety

func (*TypedFDBRecordStore[T]) RecordExists

func (ts *TypedFDBRecordStore[T]) RecordExists(primaryKey tuple.Tuple, isolationLevel IsolationLevel) (bool, error)

RecordExists checks if a record exists with the given primary key

func (*TypedFDBRecordStore[T]) SaveRecord

func (ts *TypedFDBRecordStore[T]) SaveRecord(record T) (*FDBStoredRecord[T], error)

SaveRecord saves a typed record to the store

func (*TypedFDBRecordStore[T]) SaveRecordWithOptions

func (ts *TypedFDBRecordStore[T]) SaveRecordWithOptions(
	record T,
	existenceCheck RecordExistenceCheck,
) (*FDBStoredRecord[T], error)

SaveRecordWithOptions saves a typed record with existence checking

func (*TypedFDBRecordStore[T]) ScanRecords

func (ts *TypedFDBRecordStore[T]) ScanRecords(continuation []byte, scanProperties ScanProperties) RecordCursor[*FDBStoredRecord[T]]

ScanRecords returns a typed cursor scanning all records of this store's type. Records are auto-filtered to the store's type and type-asserted to T.

func (*TypedFDBRecordStore[T]) Subspace

func (ts *TypedFDBRecordStore[T]) Subspace() subspace.Subspace

Subspace returns the subspace this store is using

func (*TypedFDBRecordStore[T]) UpdateRecord

func (ts *TypedFDBRecordStore[T]) UpdateRecord(record T) (*FDBStoredRecord[T], error)

UpdateRecord saves a typed record and throws an error if it does not already exist or if its type has changed

type UniquenessViolation

type UniquenessViolation struct {
	IndexName   string
	IndexKey    tuple.Tuple
	PrimaryKey  tuple.Tuple
	ExistingKey tuple.Tuple // Conflicting PK stored by the other side (may be nil)
}

UniquenessViolation represents a recorded uniqueness violation entry. Matches Java's RecordIndexUniquenessViolation.

type UnknownOrElseCursorStateError

type UnknownOrElseCursorStateError struct{}

UnknownOrElseCursorStateError is returned when an OrElse continuation carries a state value outside the known OrElseContinuation_State range. Matches Java's OrElseCursor.UnknownOrElseCursorStateException.

func (*UnknownOrElseCursorStateError) Error

type UnknownStoreLockStateError

type UnknownStoreLockStateError struct {
	LockStateValue int32
}

UnknownStoreLockStateError is returned when a store has an unrecognized lock state at FormatVersion >= FULL_STORE_LOCK (14). This prevents opening stores with lock states added by newer versions that we don't understand. Matches Java's com.apple.foundationdb.record.UnknownStoreLockStateException.

func (*UnknownStoreLockStateError) Error

type UnsupportedFormatVersionError

type UnsupportedFormatVersionError struct {
	Version    int32
	MaxVersion int32
}

UnsupportedFormatVersionError is returned when a store header contains a format version higher than the maximum version this code supports. Matches Java's com.apple.foundationdb.record.provider.foundationdb.UnsupportedFormatVersionException.

func (*UnsupportedFormatVersionError) Error

type VectorMetric

type VectorMetric int

VectorMetric identifies a distance metric for HNSW vector search.

const (
	// VectorMetricEuclidean is true L2: sqrt(Σ(a_i−b_i)²). Matches Java's
	// EUCLIDEAN_METRIC (MetricDefinition.EuclideanMetric.distance = Math.sqrt(...)).
	VectorMetricEuclidean VectorMetric = iota
	VectorMetricCosine
	VectorMetricInnerProduct
	// VectorMetricEuclideanSquare is squared L2: Σ(a_i−b_i)² (no sqrt). Matches
	// Java's EUCLIDEAN_SQUARE_METRIC — same KNN ordering as L2, cheaper, but it is
	// NOT a true metric (does not satisfy the triangle inequality). Added at the end
	// so the existing iota values are unchanged (the int is never persisted; configs
	// round-trip via the option string, e.g. "EUCLIDEAN_SQUARE_METRIC").
	VectorMetricEuclideanSquare
)

type VectorQuantizer

type VectorQuantizer interface {
	// Encode quantizes a float64 vector into compact bytes for storage.
	Encode(vector []float64) []byte

	// Distance estimates the distance between a raw query vector and stored
	// quantized bytes. Returns the estimated distance.
	Distance(query []float64, storedBytes []byte, numDimensions int) (float64, error)

	// Decode reconstructs an approximate float64 vector from stored quantized bytes.
	// Used for pairwise distance in the neighbor selection heuristic.
	Decode(storedBytes []byte, numDimensions int) ([]float64, error)

	// GetTypeByte returns the type ordinal byte used as the first byte of encoded data.
	// This is used to dispatch between raw and quantized storage.
	GetTypeByte() byte
}

VectorQuantizer is an optional quantization strategy for HNSW vector storage. When set on HNSWConfig, HNSW uses it for encoding, distance estimation, and vector reconstruction instead of raw float64 storage.

This interface allows quantization implementations (like RaBitQ) to live in separate packages, matching Java's architecture where RaBitQ is in fdb-extensions.

type VectorScanBounds

type VectorScanBounds struct {
	QueryVector []float64 // The query vector for similarity search.
	K           int       // Number of nearest neighbors to return.
	EfSearch    int       // Search exploration factor (0 = auto from K).
}

VectorScanBounds carries the parameters for a BY_DISTANCE kNN scan. Matches Java's VectorIndexScanBounds (query vector, k limit, efSearch, options).

type VectorSearchResult

type VectorSearchResult struct {
	PrimaryKey tuple.Tuple
	Distance   float64
}

VectorSearchResult is a single result from a vector similarity search.

func SearchSPFreshIndex

func SearchSPFreshIndex(store *FDBRecordStore, indexName string, queryVector []float64, k int) ([]VectorSearchResult, error)

SearchSPFreshIndex runs a kNN search against a readable SPFresh index, returning up to k nearest primary keys (with exact, sidecar-re-ranked distances, ascending) to queryVector using the index's default probe budget. It is the SPFresh counterpart to FDBRecordStore.SearchVectorIndex (vector_index_maintainer.go), which type-asserts the HNSW maintainer and rejects SPFresh. Callers needing per-query probe knobs (k, kc, w, c, ε) drive ScanByDistance through the executor instead.

Returns *IndexNotReadableError if the index is not scannable (matching the HNSW SearchVectorIndex contract). NOT purely read-only: like the SPFresh read path it shares (searchCurrentGeneration), a probe that reads a posting at the 4×Lmax+1 cap re-files that posting's split task (the read-path envelope repair) — a write the surrounding transaction commits. On a maintained index no posting is over the cap, so the common path performs no writes.

type VersionKeyExpression

type VersionKeyExpression struct{}

VersionKeyExpression extracts the record version as a Versionstamp tuple element. Used by VERSION indexes to index records by their commit version. Matches Java's com.apple.foundationdb.record.metadata.expressions.VersionKeyExpression.

func VersionKey

func VersionKey() *VersionKeyExpression

VersionKey creates a key expression that evaluates to the record's version. Matches Java's Key.Expressions.version().

func (*VersionKeyExpression) ColumnSize

func (v *VersionKeyExpression) ColumnSize() int

ColumnSize returns 1 — a version expression produces a single tuple element.

func (*VersionKeyExpression) Evaluate

func (v *VersionKeyExpression) Evaluate(record *FDBStoredRecord[proto.Message], _ proto.Message) ([][]any, error)

Evaluate returns the record's version as a Versionstamp. For complete versions, returns a complete tuple.Versionstamp. For incomplete versions, returns an incomplete tuple.Versionstamp (with placeholder bytes). If record or version is nil, returns [[nil]]. Matches Java's VersionKeyExpression.evaluateMessage().

func (*VersionKeyExpression) FieldNames

func (v *VersionKeyExpression) FieldNames() []string

FieldNames returns an empty slice — version expressions don't access proto fields.

func (*VersionKeyExpression) ToKeyExpression

func (v *VersionKeyExpression) ToKeyExpression() *gen.KeyExpression

ToKeyExpression serializes a VersionKeyExpression to proto. Matches Java's VersionKeyExpression.toKeyExpression().

type VersionMutationType

type VersionMutationType int

VersionMutationType represents the type of versionstamp mutation. Matches Java's MutationType used in FDBRecordContext.addVersionMutation().

const (
	// MutationTypeSetVersionstampedValue queues a SET_VERSIONSTAMPED_VALUE mutation.
	MutationTypeSetVersionstampedValue VersionMutationType = iota
	// MutationTypeSetVersionstampedKey queues a SET_VERSIONSTAMPED_KEY mutation.
	MutationTypeSetVersionstampedKey
)

type WeakReadSemantics

type WeakReadSemantics struct {
	// MinVersion is the minimum read version acceptable. If the cached read
	// version is >= MinVersion, it will be reused without a GRV round-trip.
	MinVersion int64

	// StalenessBoundMillis is the maximum staleness (in ms) of a cached read
	// version. If the cached version is older than this, a fresh GRV is fetched.
	StalenessBoundMillis int64

	// IsCausalReadRisky sets the FDB_TR_OPTION_CAUSAL_READ_RISKY flag.
	// This allows the transaction to read from any storage replica, not
	// just the one with the latest committed data.
	IsCausalReadRisky bool
}

WeakReadSemantics configures relaxed read consistency for a transaction. When provided, the transaction may read at a slightly stale version, reducing GRV latency at the cost of freshness. Matches Java's FDBDatabase.WeakReadSemantics.

Source Files

Directories

Path Synopsis
Package chaos provides model-based chaos testing for the FDB Record Layer.
Package chaos provides model-based chaos testing for the FDB Record Layer.
Package keyspace provides a logical directory tree abstraction over FDB.
Package keyspace provides a logical directory tree abstraction over FDB.
query
executor
Package executor bridges RecordQueryPlan trees (Cascades planner output) and the FDBRecordStore scanning API to produce RecordCursor[QueryResult] streams.
Package executor bridges RecordQueryPlan trees (Cascades planner output) and the FDBRecordStore scanning API to produce RecordCursor[QueryResult] streams.
plan/cascades
derivations_evaluator.go — evaluates DerivationsProperty for physical plan wrapper expressions.
derivations_evaluator.go — evaluates DerivationsProperty for physical plan wrapper expressions.
plan/cascades/expressions
Package expressions ports the Cascades-side relational expression hierarchy from Java's `com.apple.foundationdb.record.query.plan.cascades.expressions`.
Package expressions ports the Cascades-side relational expression hierarchy from Java's `com.apple.foundationdb.record.query.plan.cascades.expressions`.
plan/cascades/properties
Package properties — Cardinality and Cardinalities types.
Package properties — Cardinality and Cardinalities types.
plan/cascades/values
Package values is the Value-tier of the Go Cascades planner port — scalar / row-context expressions that compose into predicates, projections, and join keys.
Package values is the Value-tier of the Go Cascades planner port — scalar / row-context expressions that compose into predicates, projections, and join keys.
plan/plans
Go extension — no Java equivalent.
Go extension — no Java equivalent.
Package vectorcodec is the on-disk byte codec for HNSW vector columns, wire-compatible with Java's RealVector.fromBytes / VectorType.
Package vectorcodec is the on-disk byte codec for HNSW vector columns, wire-compatible with Java's RealVector.fromBytes / VectorType.

Jump to

Keyboard shortcuts

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