metadata

package
v0.0.0-...-741f41f Latest Latest
Warning

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

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

Documentation

Overview

Package metadata provides concrete bridge implementations of the api.* metadata interfaces backed by *recordlayer.RecordMetaData.

Mirrors Java's RecordLayerSchemaTemplate / RecordLayerTable / RecordLayerColumn / RecordLayerIndex types — the bridge between the SQL layer's declarative view of schema and the record-layer storage engine's proto-descriptor view.

Direction of dependency: the relational layer depends on the record layer, never the other way. Don't reach back from pkg/recordlayer into pkg/relational.

Java-compliance notes

The proto-to-DataType mapping in proto_types.go mirrors Java's com.apple.foundationdb.record.query.plan.cascades.typing.Type (fromProtobufFieldDescriptor + Record.fromDescriptorPreservingName) exactly for the cases that matter today:

  • scalar kinds → primitive types (IntegerType / LongType / etc)
  • enum → EnumType with declared values
  • message / group → recursive StructType, with two short-circuits: (a) com.apple.foundationdb.record.UUID → UUIDType, and (b) "message M { repeated R values = 1; }" nullable-array wrapper → ArrayType (see unwrapWrappedArray / Java's NullableArrayTypeUtils.describesWrappedArray)
  • repeated → ArrayType(element)
  • map → UnresolvedType

No known behavioural divergences from Java remain in this bridge for the Phase 3 primary path. Edge cases the Java side also has acknowledged TODOs about (table-level nullable=true, maps as UnresolvedType, auxiliary types from Union enums) mirror Java's behaviour rather than Java's intent.

Doesn't block the Phase 3 semantic analyzer on the primary path (CRUD over typed proto records + basic aggregations).

Version semantics

SchemaTemplate.Version() is catalog-level and decoupled from RecordMetaData.Version(). The default constructor NewRecordLayerSchemaTemplate passes md.Version() for convenience, but NewRecordLayerSchemaTemplateWithVersion lets the catalog pin a different value — matches Java's fromRecordMetadata(md, name, version) signature exactly. Catalogs that want to increment the schema version without also rebuilding storage metadata need the explicit-version constructor.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Builder

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

Builder constructs a RecordLayerSchemaTemplate from SQL-level table definitions without requiring a pre-compiled protobuf FileDescriptor.

Mirrors Java's RecordLayerSchemaTemplate.Builder at the level needed for CREATE SCHEMA TEMPLATE DDL: name, version, tables with typed columns and primary keys, and store-level flags.

func NewSchemaTemplateBuilder

func NewSchemaTemplateBuilder() *Builder

NewSchemaTemplateBuilder returns a Builder with sensible defaults (enableLongRows=true, version=1). Matches Java's default.

func (*Builder) AddAggregateIndex

func (b *Builder) AddAggregateIndex(tableName, indexName string, groupColumns []string, aggType, aggColumn string) *Builder

AddAggregateIndex registers an aggregate index (SUM, COUNT, MIN, MAX) on the named table. groupColumns are the GROUP BY columns; aggColumn is the aggregated column (empty for COUNT). aggType is one of "SUM", "COUNT", "MIN", "MAX".

func (*Builder) AddCardinalityIndex

func (b *Builder) AddCardinalityIndex(tableName, indexName, cardColumn string) *Builder

AddCardinalityIndex registers a CARDINALITY() value index on the named table. cardColumn is the array column whose element count forms the single key column (possibly dotted for an array nested in a struct, e.g. "struct.int_arr"). The index key is built as FunctionExpr("cardinality", field(col, Concatenate)) at materialise time. Must be called after the table is registered via AddTable.

func (*Builder) AddIndex

func (b *Builder) AddIndex(tableName, indexName string, columns []string, unique bool) *Builder

AddIndex registers a VALUE index on the named table. columns is the ordered list of field names that form the index key. unique causes uniqueness enforcement to be wired into the recordlayer index. Must be called after the table is registered via AddTable. Returns the builder unchanged (and records a deferred error) if the table name is unknown or any column name is not present in the table definition.

func (*Builder) AddTable

func (b *Builder) AddTable(name string, columns []ColumnSpec, primaryKey []string) *Builder

AddTable registers a table definition. columns must be listed in declared order; primaryKey is the ordered slice of column names.

func (*Builder) AddVectorIndex

func (b *Builder) AddVectorIndex(tableName, indexName, vectorColumn string, partitionColumns []string, options map[string]string) *Builder

AddVectorIndex registers a VECTOR (HNSW) index on the named table. vectorColumn is the single indexed vector field; partitionColumns form the HNSW partition prefix (each distinct partition value gets its own independent graph). options carries the HNSW tuning keys (metric, ef_construction, m, ...). The vector column must be declared with a VECTOR(dims, ...) type; the dimension count is derived from it.

Mirrors Java's DdlVisitor.visitVectorIndexDefinition, which requires exactly one indexed column of VECTOR type and derives HNSW_NUM_DIMENSIONS from the column's VectorType. AddVectorIndex registers an HNSW vector index (the default method).

func (*Builder) AddVectorIndexUsing

func (b *Builder) AddVectorIndexUsing(method, tableName, indexName, vectorColumn string, partitionColumns []string, options map[string]string) *Builder

AddVectorIndexUsing registers a vector index with an explicit method: "HNSW" (graph, Java-compatible wire format) or "SPFRESH" (RFC-094 centroid+posting-list, Go-native). SPFresh does not support PARTITION BY.

func (*Builder) Build

func (b *Builder) Build() (*RecordLayerSchemaTemplate, error)

Build materialises the schema template. Returns an error when no tables are registered or types cannot be mapped to proto field types.

func (*Builder) SetEnableLongRows

func (b *Builder) SetEnableLongRows(v bool) *Builder

func (*Builder) SetIntermingleTables

func (b *Builder) SetIntermingleTables(v bool) *Builder

func (*Builder) SetName

func (b *Builder) SetName(name string) *Builder

func (*Builder) SetStoreRowVersions

func (b *Builder) SetStoreRowVersions(v bool) *Builder

func (*Builder) SetVersion

func (b *Builder) SetVersion(v int) *Builder

type ColumnSpec

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

ColumnSpec describes a single column within a table.

func NewColumnSpec

func NewColumnSpec(name string, dt api.DataType, fieldNum int32) ColumnSpec

NewColumnSpec constructs a ColumnSpec for use with Builder.AddTable.

type RecordLayerColumn

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

RecordLayerColumn adapts a single protobuf field descriptor to the api.Column interface. Zero value is not useful — build via newColumn().

func (*RecordLayerColumn) Accept

func (c *RecordLayerColumn) Accept(v api.Visitor)

Accept dispatches into the Visitor.

func (*RecordLayerColumn) DataType

func (c *RecordLayerColumn) DataType() api.DataType

DataType returns the column's SQL type.

func (*RecordLayerColumn) FieldDescriptor

func (c *RecordLayerColumn) FieldDescriptor() protoreflect.FieldDescriptor

FieldDescriptor exposes the underlying proto field descriptor for callers that need the raw proto view (e.g. wire-format decoding). Not part of api.Column.

func (*RecordLayerColumn) MetadataName

func (c *RecordLayerColumn) MetadataName() string

MetadataName returns the column name.

type RecordLayerIndex

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

RecordLayerIndex adapts a *recordlayer.Index (plus its owning record type name) to api.Index.

Java's RecordLayerIndex.isSparse() returns `predicate != null` — a predicate-filtered index is considered sparse. recordlayer.Index has an equivalent Predicate field, so we apply the same rule.

func (*RecordLayerIndex) Accept

func (i *RecordLayerIndex) Accept(v api.Visitor)

Accept dispatches into the Visitor.

func (*RecordLayerIndex) IndexColumnNames

func (i *RecordLayerIndex) IndexColumnNames() []string

IndexColumnNames returns the field names from the index's root key expression. Satisfies cascades.IndexDef.

func (*RecordLayerIndex) IndexIsUnique

func (i *RecordLayerIndex) IndexIsUnique() bool

IndexIsUnique returns whether the index enforces uniqueness. Satisfies cascades.IndexDef.

func (*RecordLayerIndex) IndexName

func (i *RecordLayerIndex) IndexName() string

IndexName returns the index name. Satisfies cascades.IndexDef.

func (*RecordLayerIndex) IndexPrimaryKeyColumns

func (i *RecordLayerIndex) IndexPrimaryKeyColumns() []string

IndexPrimaryKeyColumns returns nil. This type is only used by the metadata visitor pattern (api.Visitor), never passed to NewPlanContextFromIndexDefs. The production Cascades path uses metadataIndexDef (cascades_generator.go) which returns real PK columns. Satisfies cascades.IndexDef.

func (*RecordLayerIndex) IndexRecordTypes

func (i *RecordLayerIndex) IndexRecordTypes() []string

IndexRecordTypes returns the owning record type. Satisfies cascades.IndexDef.

func (*RecordLayerIndex) IndexType

func (i *RecordLayerIndex) IndexType() string

IndexType returns the record-layer index-type constant ("VALUE", "COUNT", "SUM", "RANK", ...).

func (*RecordLayerIndex) IsSparse

func (i *RecordLayerIndex) IsSparse() bool

IsSparse matches Java's RecordLayerIndex.isSparse() which is "predicate != null" — a predicate-filtered index is sparse because only records matching the predicate have entries.

func (*RecordLayerIndex) IsUnique

func (i *RecordLayerIndex) IsUnique() bool

IsUnique delegates to the underlying recordlayer.Index, which reads IndexOptions.UNIQUE_OPTION — matches Java's Index.isUnique().

func (*RecordLayerIndex) MetadataName

func (i *RecordLayerIndex) MetadataName() string

MetadataName returns the index name.

func (*RecordLayerIndex) TableName

func (i *RecordLayerIndex) TableName() string

TableName returns the name of the record type (table) this index belongs to. For universal indexes the name is empty — callers that care must check HasUniversalOwner() or inspect the metadata.

func (*RecordLayerIndex) Underlying

func (i *RecordLayerIndex) Underlying() *recordlayer.Index

Underlying exposes the record-layer Index for callers that need access to its root expression, options, version metadata, etc.

type RecordLayerSchemaTemplate

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

RecordLayerSchemaTemplate is the concrete api.SchemaTemplate backed by a *recordlayer.RecordMetaData.

Construction materialises every table + index up front so lookups are O(1) and the template is safe for concurrent reads. The underlying RecordMetaData is assumed immutable (matching Java's RecordMetaData invariant).

Views / invoked routines / temporary routines are stub-empty — record-layer has no native equivalents, and the SQL-level stores for them land in a later phase (catalog storage layer). Same for the transaction-bound diagnostic string.

func NewRecordLayerSchemaTemplate

func NewRecordLayerSchemaTemplate(name string, md *recordlayer.RecordMetaData) (*RecordLayerSchemaTemplate, error)

NewRecordLayerSchemaTemplate builds the bridge with the underlying RecordMetaData's version. Equivalent to Java's RecordLayerSchemaTemplate.fromRecordMetadata(md, name, md.getVersion()). Use NewRecordLayerSchemaTemplateWithVersion when the catalog-level version should differ from the storage-level version.

Returns an error when md is nil so callers at boundary layers (DSN parsing, RPC handlers) get a clean failure rather than a panic.

func NewRecordLayerSchemaTemplateWithVersion

func NewRecordLayerSchemaTemplateWithVersion(name string, md *recordlayer.RecordMetaData, version int) (*RecordLayerSchemaTemplate, error)

NewRecordLayerSchemaTemplateWithVersion mirrors Java's RecordMetadataDeserializer.getSchemaTemplate(name, version): the schema-template version is independent of RecordMetaData.Version(), which the record-layer storage engine uses for its own bookkeeping. The catalog bumps the template version on every DDL change, and that number is what api.SchemaTemplate.Version() reports.

func (*RecordLayerSchemaTemplate) Accept

func (s *RecordLayerSchemaTemplate) Accept(v api.Visitor)

Accept runs Java's visitor cascade:

startVisit → visit → <tables.accept> → <routines.accept> → <views.accept> → finishVisit

Matches RecordLayerSchemaTemplate.accept() in the Java tree. The package-level api.VisitSchemaTemplateTree only handles the start/visit/finish triple — it cannot iterate children because api.SchemaTemplate returns typed child collections (Tables/Views/ Routines) via methods that can error. We override here so the cascade matches Java behaviour.

func (*RecordLayerSchemaTemplate) EnableLongRows

func (s *RecordLayerSchemaTemplate) EnableLongRows() bool

EnableLongRows delegates to the underlying metadata's splitLongRecords flag.

func (*RecordLayerSchemaTemplate) FindInvokedRoutine

func (s *RecordLayerSchemaTemplate) FindInvokedRoutine(_ string) (api.InvokedRoutine, error)

FindInvokedRoutine returns (nil, nil).

func (*RecordLayerSchemaTemplate) FindTable

func (s *RecordLayerSchemaTemplate) FindTable(name string) (api.Table, error)

FindTable looks up a table by exact name; returns (nil, nil) when not found.

func (*RecordLayerSchemaTemplate) FindView

func (s *RecordLayerSchemaTemplate) FindView(_ string) (api.View, error)

FindView returns (nil, nil) — same rationale as Views.

func (*RecordLayerSchemaTemplate) GenerateSchema

func (s *RecordLayerSchemaTemplate) GenerateSchema(databaseID, schemaName string) api.Schema

GenerateSchema materialises an api.Schema bound to databaseID + schemaName. Mirrors Java's factory method.

func (*RecordLayerSchemaTemplate) Indexes

func (s *RecordLayerSchemaTemplate) Indexes() ([]string, error)

Indexes returns every index name declared in this template, in sorted order. Matches Java's flat-list semantics.

func (*RecordLayerSchemaTemplate) IntermingleTables

func (s *RecordLayerSchemaTemplate) IntermingleTables() bool

IntermingleTables mirrors Java's RecordLayerSchemaTemplate.isIntermingleTables() which is !RecordMetaData.primaryKeyHasRecordTypePrefix(). When the underlying metadata has no RecordTypeKey prefix on primary keys, rows from different record types share the same keyspace prefix and the SQL layer treats them as intermingled.

func (*RecordLayerSchemaTemplate) InvokedRoutines

func (s *RecordLayerSchemaTemplate) InvokedRoutines() ([]api.InvokedRoutine, error)

InvokedRoutines is always empty — stored routines (UDFs) are a SQL-layer concept not backed by record-layer.

func (*RecordLayerSchemaTemplate) MetadataName

func (s *RecordLayerSchemaTemplate) MetadataName() string

MetadataName returns the template name provided at construction.

func (*RecordLayerSchemaTemplate) StoreRowVersions

func (s *RecordLayerSchemaTemplate) StoreRowVersions() bool

StoreRowVersions delegates to the underlying metadata's storeRecordVersions flag.

func (*RecordLayerSchemaTemplate) TableIndexMapping

func (s *RecordLayerSchemaTemplate) TableIndexMapping() (map[string][]string, error)

TableIndexMapping returns a map of tableName → index names. Deterministic: both outer keys and inner slices are sorted.

func (*RecordLayerSchemaTemplate) Tables

func (s *RecordLayerSchemaTemplate) Tables() ([]api.Table, error)

Tables returns the tables in deterministic (sorted-by-name) order. Error slot is reserved for future catalog-backed implementations; this bridge never returns an error.

func (*RecordLayerSchemaTemplate) TemporaryInvokedRoutines

func (s *RecordLayerSchemaTemplate) TemporaryInvokedRoutines() ([]api.InvokedRoutine, error)

TemporaryInvokedRoutines is always empty.

func (*RecordLayerSchemaTemplate) TransactionBoundMetadataAsString

func (s *RecordLayerSchemaTemplate) TransactionBoundMetadataAsString() (string, error)

TransactionBoundMetadataAsString is a diagnostic string. The Java side tags each transaction-bound piece; we have none, so return an empty string.

func (*RecordLayerSchemaTemplate) Underlying

Underlying exposes the record-layer metadata for callers that need proto-descriptor-level access (e.g. the query executor).

func (*RecordLayerSchemaTemplate) Version

func (s *RecordLayerSchemaTemplate) Version() int

Version returns the schema-template version. Matches Java's SchemaTemplate.getVersion() — independent from RecordMetaData.getVersion(); the caller passes the catalog-level version to NewRecordLayerSchemaTemplateWithVersion, or NewRecordLayerSchemaTemplate uses RecordMetaData.Version() as a sensible default.

func (*RecordLayerSchemaTemplate) Views

func (s *RecordLayerSchemaTemplate) Views() ([]api.View, error)

Views always returns nil — record-layer has no views today.

type RecordLayerTable

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

RecordLayerTable adapts a recordlayer.RecordType to api.Table.

The view is computed eagerly at construction so repeated Columns() / StructDataType() calls are cheap; if that becomes a problem we can switch to lazy caching. Current sizes (dozens of fields) make it not worth optimising.

func (*RecordLayerTable) Accept

func (t *RecordLayerTable) Accept(v api.Visitor)

Accept dispatches into the Visitor. The default cascade visits the table itself, then its indexes and columns — mirroring Java's Table.accept().

func (*RecordLayerTable) Columns

func (t *RecordLayerTable) Columns() []api.Column

Columns returns the columns in declared order.

func (*RecordLayerTable) Indexes

func (t *RecordLayerTable) Indexes() []api.Index

Indexes returns the indexes on this table.

func (*RecordLayerTable) MetadataName

func (t *RecordLayerTable) MetadataName() string

MetadataName returns the table (record-type) name.

func (*RecordLayerTable) RecordType

func (t *RecordLayerTable) RecordType() *recordlayer.RecordType

RecordType exposes the underlying record-layer type for callers that need its proto descriptor, primary key, etc.

func (*RecordLayerTable) StructDataType

func (t *RecordLayerTable) StructDataType() *api.StructType

StructDataType returns the table's composite struct type.

Jump to

Keyboard shortcuts

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