catalog

package
v0.2.0 Latest Latest
Warning

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

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

Documentation

Overview

Package catalog contains concrete implementations of the api.StoreCatalog / api.SchemaTemplateCatalog / api.Transaction interfaces.

The in-memory implementation (InMemoryStoreCatalog + friends) is intended for unit tests and development — it keeps the whole catalog in a mutex-protected map. It does NOT implement real multi-writer transactional isolation; concurrent SaveSchema / Commit across two live transactions may interleave in ways a real FDB-backed impl wouldn't.

The Java-compatible FDB-backed catalog is RecordLayerStoreCatalog (fdb_store_catalog.go).

Index

Constants

View Source
const (
	// SysConstant is the root system namespace ("__SYS"). Contains
	// the catalog's own record store.
	SysConstant = "__SYS"

	// CatalogConstant is the schema name inside __SYS that holds the
	// catalog records (DATABASE_INFO, SCHEMA, SCHEMA_TEMPLATE).
	CatalogConstant = "CATALOG"

	// DBNameDir is the KeySpaceDirectory name for a database entry
	// under a domain.
	DBNameDir = "dbName"

	// SchemaDir is the KeySpaceDirectory name for a schema entry
	// under a database.
	SchemaDir = "schema"

	// DefaultSchemaDir marks the "default" schema child directory
	// (used for convenience-resolution today per Java).
	DefaultSchemaDir = "defaultSchema"

	// InterningLayer is the dedicated subspace name for the
	// interning-layer string resolver (turns long domain / db names
	// into short integer IDs).
	InterningLayer = "__internedStrings"

	// InterningLayerValue is the fixed scalar stored at the
	// interning-layer subspace (two-byte sentinel "IL").
	InterningLayerValue = "IL"
)

Keyspace-path constants for the FDB-backed catalog. Mirrors Java's com.apple.foundationdb.relational.recordlayer.RelationalKeyspaceProvider byte-for-byte so the on-FDB layout is cross-language compatible.

Layout:

/                              — root
└── __SYS                      — system schema (SysConstant)
    └── CATALOG                — catalog schema (CatalogConstant)
└── <domain name>              — user domains (naïve today per Java)
    └── <dbName>               — DB_NAME_DIR child
        └── <schema>           — SCHEMA_DIR child

Used by the (not-yet-landed) FDB-backed RecordLayerStoreCatalog to construct KeySpacePaths. Defining the constants here now keeps the whole catalog package as the single source of truth for the SQL-layer-side of the layout; the FDB impl will import these.

View Source
const (
	ColDatabaseID      = "DATABASE_ID"
	ColSchemaName      = "SCHEMA_NAME"
	ColTemplateName    = "TEMPLATE_NAME"
	ColTemplateVersion = "TEMPLATE_VERSION"
	ColMetaData        = "META_DATA"

	// Indexes on SCHEMAS.
	IdxTemplatesCount = "TEMPLATES_COUNT_INDEX"
	IdxTemplatesValue = "TEMPLATES_VALUE_INDEX"
	// Index on DATABASES.
	IdxDatabasesCount = "DATABASES_COUNT_INDEX"
)

Catalog column / index constants. Mirror Java's com.apple.foundationdb.relational.recordlayer.catalog.systables.SystemTable + sibling table classes.

View Source
const (
	// SchemaRecordTypeKey is the RECORD_TYPE_KEY prefix for Schema
	// records in the catalog store.
	SchemaRecordTypeKey int64 = 0
	// DatabaseInfoRecordTypeKey prefixes DatabaseInfo records.
	DatabaseInfoRecordTypeKey int64 = 1
	// SchemaTemplateRecordTypeKey prefixes SchemaTemplate records.
	SchemaTemplateRecordTypeKey int64 = 2

	// SchemasTableName is the user-visible INFORMATION_SCHEMA name for
	// the Schema record type (Java: "SCHEMAS"). The Go proto descriptor
	// uses the Go-style message name "Schemas"; wire compatibility is
	// preserved because Java and Go both agree on record-type key 0
	// and on field numbers inside the Schemas/SCHEMAS message (both
	// generated programmatically with the same 1-based column layout).
	SchemasTableName = "SCHEMAS"
	// DatabaseTableName — Java-visible name for Databases records.
	DatabaseTableName = "DATABASES"
	// SchemaTemplateTableName — Java-visible name for Templates records.
	SchemaTemplateTableName = "TEMPLATES"

	// SchemasRecordName / DatabasesRecordName / TemplatesRecordName are
	// the internal proto descriptor names that recordlayer uses to
	// resolve record types. They match the message names in
	// proto/relational/catalog_data.proto.
	SchemasRecordName   = "Schemas"
	DatabasesRecordName = "Databases"
	TemplatesRecordName = "Templates"
)

System-table identity constants. Mirror Java's com.apple.foundationdb.relational.recordlayer.catalog.systables. SystemTableRegistry byte-for-byte.

RECORD_TYPE_KEY values are the leading tuple element on every catalog record in FDB — they're what distinguishes a Schema record from a Database record at the key level. Java hard-codes the numeric values; changing them breaks wire compatibility for any catalog Java has written to.

The table-name constants are the user-visible names in INFORMATION_SCHEMA / SHOW TABLES output for the system schema (__SYS/CATALOG).

View Source
const CatalogTemplateName = CatalogConstant + "_TEMPLATE"

CatalogTemplateName is the name of the catalog's own schema template. Matches Java's RecordLayerStoreCatalog.CATALOG_TEMPLATE constant ("CATALOG_TEMPLATE").

View Source
const CatalogTemplateVersion = 1

CatalogTemplateVersion is the version of the built-in catalog schema template. Java pins this to 1.

View Source
const SysDatabaseID = "/" + SysConstant

SysDatabaseID is the system database path. Java uses "/__SYS".

Variables

This section is empty.

Functions

func BuildCatalogMetaData

func BuildCatalogMetaData() (*recordlayer.RecordMetaData, error)

BuildCatalogMetaData materialises the RecordMetaData for the three catalog record types (SCHEMAS, DATABASES, TEMPLATES).

Wire layout (byte-for-byte with Java RecordLayerStoreCatalog):

SCHEMAS   — record type key 0, PK [typeKey, DATABASE_ID, SCHEMA_NAME]
DATABASES — record type key 1, PK [typeKey, DATABASE_ID]
TEMPLATES — record type key 2, PK [typeKey, TEMPLATE_NAME, TEMPLATE_VERSION]

Indexes:

SCHEMAS.TEMPLATES_COUNT_INDEX — COUNT grouped by (TEMPLATE_NAME, TEMPLATE_VERSION)
SCHEMAS.TEMPLATES_VALUE_INDEX — VALUE on (TEMPLATE_NAME, TEMPLATE_VERSION, DATABASE_ID, SCHEMA_NAME)
DATABASES.DATABASES_COUNT_INDEX — ungrouped COUNT

Returns an error only if the underlying RecordMetaDataBuilder rejects the proto descriptor; under normal conditions this cannot fail.

func DefaultCatalogSubspace

func DefaultCatalogSubspace() subspace.Subspace

DefaultCatalogSubspace returns the standard __SYS/CATALOG subspace in the exact byte layout Java writes. Java's RelationalKeyspaceProvider defines:

KeySpaceDirectory(SYS,     KeyType.NULL)                            // __SYS domain
  KeySpaceDirectory(SYS,   KeyType.NULL)                            // __SYS database
    KeySpaceDirectory(CATALOG, KeyType.LONG, 0L)                    // CATALOG schema

The directory *names* (__SYS, __SYS, CATALOG) are path labels; the on-wire tuple element for each level is the KeyType constant. So the catalog's actual subspace prefix is the tuple (NULL, NULL, int64(0)) — NOT three strings. Go previously used subspace.Sub("__SYS", "CATALOG") which encodes two string tuple elements and is incompatible with Java-written catalogs. See fdb-record-layer/.../RelationalKeyspaceProvider.java#getSystemDirectory.

The SQL driver's keyspace.RelationalKeyspace.CatalogSubspace uses the same prefix.

Types

type CatalogDatabaseMetaData

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

CatalogDatabaseMetaData implements api.DatabaseMetaData by running queries against a StoreCatalog. Suitable for JDBC-style introspection tools and for backing sql.DB.Stats-like consumers.

Each query runs in a fresh api.Transaction (new InMemoryTransaction) and closes it before returning — the ResultSet does not outlive the transaction. Callers iterating the ResultSet see a point-in-time snapshot; concurrent catalog changes after the method returns do not surface.

The Go DatabaseMetaData interface is a lean subset of Java's RelationalDatabaseMetaData — see api/database_metadata.go for what's included and what's deferred.

func NewCatalogDatabaseMetaData

func NewCatalogDatabaseMetaData(opts CatalogDatabaseMetaDataOptions) *CatalogDatabaseMetaData

NewCatalogDatabaseMetaData constructs a CatalogDatabaseMetaData. Panics if opts.StoreCatalog is nil — DatabaseMetaData without a catalog is meaningless.

func (*CatalogDatabaseMetaData) Columns

func (m *CatalogDatabaseMetaData) Columns(_ context.Context, catalog, schemaPattern, tableNamePattern, columnNamePattern string) (api.ResultSet, error)

Columns returns per-column metadata matching the given catalog / schema / table / column patterns. 24-column JDBC shape — see api/database_metadata.go for the column list and ordering.

DATA_TYPE is derived from api.JDBCType on the column's DataType. TYPE_NAME is the DataType.String() rendering. NULLABLE / IS_NULLABLE mirror DataType.IsNullable — proto2 REQUIRED fields report "NO" / ColumnNoNulls, everything else "YES" / ColumnNullable.

Columns the relational layer doesn't track (COLUMN_SIZE, DECIMAL_DIGITS, CHAR_OCTET_LENGTH, ...) surface as nil; callers iterating a real JDBC ResultSet would see them as SQL NULL.

func (*CatalogDatabaseMetaData) DatabaseProductName

func (m *CatalogDatabaseMetaData) DatabaseProductName() string

func (*CatalogDatabaseMetaData) DatabaseProductVersion

func (m *CatalogDatabaseMetaData) DatabaseProductVersion() string

func (*CatalogDatabaseMetaData) DriverName

func (m *CatalogDatabaseMetaData) DriverName() string

func (*CatalogDatabaseMetaData) DriverVersion

func (m *CatalogDatabaseMetaData) DriverVersion() string

func (*CatalogDatabaseMetaData) IndexInfo

func (m *CatalogDatabaseMetaData) IndexInfo(_ context.Context, catalog, schema, table string, unique, _ bool) (api.ResultSet, error)

IndexInfo returns per-index metadata for a single table. If unique=true, only unique indexes are returned. approximate is ignored — the in-memory catalog has no notion of stale statistics.

13-column JDBC shape. Our api.Index doesn't expose per-column position data today, so we surface a single row per index (with ORDINAL_POSITION=1, COLUMN_NAME empty). JDBC clients that walk the result by column position still see a consistent shape.

func (*CatalogDatabaseMetaData) IsReadOnly

func (m *CatalogDatabaseMetaData) IsReadOnly() bool

func (*CatalogDatabaseMetaData) PrimaryKeys

func (m *CatalogDatabaseMetaData) PrimaryKeys(_ context.Context, catalog, schema, table string) (api.ResultSet, error)

PrimaryKeys returns the primary-key columns of a single table. Each row is one PK column (key_seq 1..N). Today we surface the recordlayer-level primary key tuple as a single "compound key" row — the Java side splits into individual column rows when the PK is a composite expression, which we'll match once our key-expression introspection grows.

func (*CatalogDatabaseMetaData) Schemas

Schemas returns every schema in every catalog. Columns match JDBC DatabaseMetaData.getSchemas(): (TABLE_SCHEM, TABLE_CATALOG). TABLE_CATALOG is the database URI path; Java surfaces it as the "catalog" value in JDBC terminology.

func (*CatalogDatabaseMetaData) SchemasFiltered

func (m *CatalogDatabaseMetaData) SchemasFiltered(_ context.Context, catalog, schemaPattern string) (api.ResultSet, error)

SchemasFiltered narrows Schemas by catalog + schema LIKE patterns. Empty patterns match anything (SQL standard: no filter).

func (*CatalogDatabaseMetaData) Tables

func (m *CatalogDatabaseMetaData) Tables(_ context.Context, catalog, schemaPattern, tableNamePattern string, types []string) (api.ResultSet, error)

Tables enumerates every table in every schema matching the patterns. types optionally restricts to a subset of table types ("TABLE", "VIEW", "SYSTEM TABLE"); nil or empty returns all types.

Since our catalog today has only regular tables (no views, no system tables), every returned row has TABLE_TYPE == "TABLE" and all type columns (TYPE_CAT / TYPE_SCHEM / TYPE_NAME) are empty.

func (*CatalogDatabaseMetaData) URL

func (*CatalogDatabaseMetaData) UserName

func (m *CatalogDatabaseMetaData) UserName() string

type CatalogDatabaseMetaDataOptions

type CatalogDatabaseMetaDataOptions struct {
	// StoreCatalog: required. Backs every discovery query.
	StoreCatalog api.StoreCatalog
	// NewTransaction: factory for a fresh transaction per query. If
	// nil, a new *InMemoryTransaction is used (valid only when the
	// catalog is an InMemoryStoreCatalog).
	NewTransaction func() api.Transaction
	// URL, UserName, ReadOnly, ProductName, ProductVersion, DriverName,
	// DriverVersion: returned by the corresponding accessors.
	URL            string
	UserName       string
	ReadOnly       bool
	ProductName    string
	ProductVersion string
	DriverName     string
	DriverVersion  string
}

CatalogDatabaseMetaDataOptions configures identification fields. The storeCatalog is required; everything else is optional and defaults to sensible values.

type FDBTransaction

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

FDBTransaction bridges a *recordlayer.FDBRecordContext onto the api.Transaction interface. Mirrors Java's RecordContextTransaction: it owns no lifecycle of its own beyond the commit/abort/close state machine — the underlying FDBRecordContext handles the real FDB work.

The transaction is considered "closed" once Commit or Abort returns successfully, or Close is called. Subsequent operations return ErrCodeTransactionInactive.

func NewFDBTransaction

func NewFDBTransaction(ctx *recordlayer.FDBRecordContext) *FDBTransaction

NewFDBTransaction wraps an FDBRecordContext. The caller retains ownership of ctx; Close() does NOT cancel the underlying context (matches Java's behaviour where RecordContextTransaction.close is a no-op when the runner manages the context). Callers must Commit or Abort before discarding the transaction.

func (*FDBTransaction) Abort

func (t *FDBTransaction) Abort() error

Abort cancels the underlying FDB transaction and marks this transaction closed. Idempotent with Commit — the first of the two wins; subsequent calls return ErrCodeTransactionInactive.

func (*FDBTransaction) BoundSchemaTemplate

func (t *FDBTransaction) BoundSchemaTemplate() api.SchemaTemplate

BoundSchemaTemplate returns the template bound to this transaction, or nil.

func (*FDBTransaction) Close

func (t *FDBTransaction) Close() error

Close releases state held by this bridge. Does NOT touch the underlying FDBRecordContext — the caller that created it owns its lifecycle. Safe to call multiple times.

func (*FDBTransaction) Commit

func (t *FDBTransaction) Commit() error

Commit finalises the underlying FDB transaction. After a successful commit the transaction is marked closed; further operations error. A failed commit leaves the transaction in the pre-commit state so callers may decide whether to Abort / Close.

func (*FDBTransaction) Context

Context returns the underlying record-layer context. Catalog impls use this to open record stores; equivalent to Java's Transaction.unwrap(FDBRecordContext.class).

func (*FDBTransaction) IsClosed

func (t *FDBTransaction) IsClosed() bool

IsClosed reports whether Commit / Abort / Close has been called.

func (*FDBTransaction) SetBoundSchemaTemplate

func (t *FDBTransaction) SetBoundSchemaTemplate(template api.SchemaTemplate)

SetBoundSchemaTemplate binds or replaces the template.

func (*FDBTransaction) UnsetBoundSchemaTemplate

func (t *FDBTransaction) UnsetBoundSchemaTemplate()

UnsetBoundSchemaTemplate clears any bound template.

func (*FDBTransaction) Unwrap

func (t *FDBTransaction) Unwrap() any

Unwrap returns the underlying *recordlayer.FDBRecordContext. Satisfies api.Transaction.Unwrap — callers that need the FDB handle should go through unwrapFDB rather than asserting *FDBTransaction directly so a future decorator Transaction that forwards Unwrap continues to work.

type InMemorySchemaTemplateCatalog

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

InMemorySchemaTemplateCatalog stores schema templates keyed by (name, version). Companion to InMemoryStoreCatalog.

func NewInMemorySchemaTemplateCatalog

func NewInMemorySchemaTemplateCatalog() *InMemorySchemaTemplateCatalog

NewInMemorySchemaTemplateCatalog returns an empty template catalog.

func (*InMemorySchemaTemplateCatalog) CreateTemplate

func (c *InMemorySchemaTemplateCatalog) CreateTemplate(txn api.Transaction, newTemplate api.SchemaTemplate) error

CreateTemplate persists a new (name, version) through the FDB catalog's route (RecordLayerStoreSchemaTemplateCatalog.CreateTemplate): the exact-duplicate refusal, then refuseBelowLatest against the latest stored version, the version guard, and for a new version of a stored name the carry from the latest version's ToProto (carryTemplate, with the lane check over the indexes it defines). What is stored is the template the carried bytes load as; a fresh name is lane-checked (checkIndexLanes) and stored as given, and so is a template that is not a RecordLayerSchemaTemplate, which has no meta-data to carry or check.

func (*InMemorySchemaTemplateCatalog) DeleteTemplate

func (c *InMemorySchemaTemplateCatalog) DeleteTemplate(txn api.Transaction, templateName string, throwIfDoesNotExist bool) error

DeleteTemplate removes every version of templateName.

func (*InMemorySchemaTemplateCatalog) DeleteTemplateVersion

func (c *InMemorySchemaTemplateCatalog) DeleteTemplateVersion(txn api.Transaction, templateName string, version int, throwIfDoesNotExist bool) error

DeleteTemplateVersion removes one specific (name, version). A version a schema binds is not deleted (the version guard, template_bindings.go).

func (*InMemorySchemaTemplateCatalog) DoesSchemaTemplateExist

func (c *InMemorySchemaTemplateCatalog) DoesSchemaTemplateExist(txn api.Transaction, templateName string) (bool, error)

DoesSchemaTemplateExist: any version of templateName.

func (*InMemorySchemaTemplateCatalog) DoesSchemaTemplateExistAtVersion

func (c *InMemorySchemaTemplateCatalog) DoesSchemaTemplateExistAtVersion(txn api.Transaction, templateName string, version int) (bool, error)

DoesSchemaTemplateExistAtVersion: specific (name, version).

func (*InMemorySchemaTemplateCatalog) ListTemplates

ListTemplates returns every (name, version) pair, sorted by (name, version).

func (*InMemorySchemaTemplateCatalog) LoadSchemaTemplate

func (c *InMemorySchemaTemplateCatalog) LoadSchemaTemplate(txn api.Transaction, templateName string) (api.SchemaTemplate, error)

LoadSchemaTemplate returns the highest-versioned template with the given name. ErrCodeUnknownSchemaTemplate when not found.

func (*InMemorySchemaTemplateCatalog) LoadSchemaTemplateAtVersion

func (c *InMemorySchemaTemplateCatalog) LoadSchemaTemplateAtVersion(txn api.Transaction, templateName string, version int) (api.SchemaTemplate, error)

LoadSchemaTemplateAtVersion returns one specific (name, version).

func (*InMemorySchemaTemplateCatalog) LoadTemplateProto

func (c *InMemorySchemaTemplateCatalog) LoadTemplateProto(txn api.Transaction, templateName string, version int) (*gen.MetaData, error)

LoadTemplateProto returns the stored template's MetaData. The in-memory catalog keeps template objects and no bytes, so this is the template's ToProto: it holds only templates Go built, through CreateTemplate, so there is no unknown field or extension another engine wrote for it to lose.

type InMemoryStoreCatalog

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

InMemoryStoreCatalog keeps the entire catalog (databases + schemas) in a mutex-protected map. Intended for unit tests and development; the FDB-backed implementation is RecordLayerStoreCatalog.

A single InMemoryStoreCatalog instance is safe for concurrent use across transactions — the mutex serialises the full state — but does NOT implement MVCC. Readers see whatever the latest writer committed; aborts are no-ops.

func NewInMemoryStoreCatalog

func NewInMemoryStoreCatalog() *InMemoryStoreCatalog

NewInMemoryStoreCatalog returns a fresh, empty catalog.

func (*InMemoryStoreCatalog) CreateDatabase

func (c *InMemoryStoreCatalog) CreateDatabase(txn api.Transaction, dbURI string) error

CreateDatabase records a new database. Returns ErrCodeDatabaseAlreadyExists when dbURI is already present.

func (*InMemoryStoreCatalog) DeleteDatabase

func (c *InMemoryStoreCatalog) DeleteDatabase(txn api.Transaction, dbURI string, throwIfDoesNotExist bool) (bool, error)

DeleteDatabase removes a database and all its schemas. Always returns true on success — the in-memory path never partially completes (no time limit).

func (*InMemoryStoreCatalog) DeleteSchema

func (c *InMemoryStoreCatalog) DeleteSchema(txn api.Transaction, dbURI, schemaName string) error

DeleteSchema removes (dbURI, schemaName).

func (*InMemoryStoreCatalog) DoesDatabaseExist

func (c *InMemoryStoreCatalog) DoesDatabaseExist(txn api.Transaction, dbURI string) (bool, error)

DoesDatabaseExist returns true iff dbURI is present.

func (*InMemoryStoreCatalog) DoesSchemaExist

func (c *InMemoryStoreCatalog) DoesSchemaExist(txn api.Transaction, dbURI, schemaName string) (bool, error)

DoesSchemaExist returns true iff (dbURI, schemaName) resolves.

func (*InMemoryStoreCatalog) ListDatabases

func (c *InMemoryStoreCatalog) ListDatabases(txn api.Transaction, _ api.Continuation) (api.ResultSet, error)

ListDatabases returns a sorted ResultSet of (database_name) rows. Continuations are ignored for the in-memory impl.

func (*InMemoryStoreCatalog) ListSchemas

ListSchemas returns a ResultSet of (database_name, schema_name) rows across every database.

func (*InMemoryStoreCatalog) ListSchemasInDatabase

func (c *InMemoryStoreCatalog) ListSchemasInDatabase(txn api.Transaction, databaseID string, _ api.Continuation) (api.ResultSet, error)

ListSchemasInDatabase narrows ListSchemas to a single database.

func (*InMemoryStoreCatalog) LoadSchema

func (c *InMemoryStoreCatalog) LoadSchema(txn api.Transaction, databaseID, schemaName string) (api.Schema, error)

LoadSchema looks up a Schema by (databaseID, schemaName).

Java compliance: RecordLayerStoreCatalog.loadSchema always returns UNDEFINED_SCHEMA regardless of whether the database exists or only the schema is missing. The underlying primary key Tuple is (RECORD_TYPE_KEY, dbPath, schemaName) so "no record found" is the only observable state — we collapse both misses to ErrCodeUndefinedSchema to match.

func (*InMemoryStoreCatalog) RepairSchema

func (c *InMemoryStoreCatalog) RepairSchema(txn api.Transaction, databaseID, schemaName string) error

RepairSchema rebinds schemaName to the latest version of its owning template, as Java's repairSchema: it loads the schema with its template (refused when the bound version is gone) and saves it onto the latest version with UPGRADE, through saveSchemaHeld and so the rebind validator. The mutex is held throughout, so the template reads and the write see one state.

func (*InMemoryStoreCatalog) SaveSchema

func (c *InMemoryStoreCatalog) SaveSchema(txn api.Transaction, dataToWrite api.Schema, createDatabaseIfNecessary bool, existsBehavior api.SchemaExistsBehavior) error

SaveSchema persists schema, in Java's saveSchema order, as the FDB catalog's SaveSchema: validate the schema; the database exists (else UNDEFINED_DATABASE unless createDatabaseIfNecessary); the template exists at the schema's version (UNKNOWN_SCHEMA_TEMPLATE); the stored row loads with its template, which fails when that version is gone; existsBehavior decides a save over a stored row, and Go's rebind validator checks one that overwrites it; write.

Note the error codes: UNDEFINED_DATABASE here, not UNKNOWN_DATABASE — those are two distinct SQLSTATEs in Java.

func (*InMemoryStoreCatalog) SchemaTemplateCatalog

func (c *InMemoryStoreCatalog) SchemaTemplateCatalog() api.SchemaTemplateCatalog

SchemaTemplateCatalog returns the nested template catalog.

type InMemoryTransaction

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

InMemoryTransaction is a minimal api.Transaction for tests. Concurrent calls to any method after Close / Commit / Abort return ErrCodeTransactionInactive. State is protected by a mutex; there is no MVCC, no write buffer — changes against the catalog are applied directly and a later Abort does NOT roll them back.

Good enough for unit tests; a real FDB transaction is required before running SQL over live data.

func NewInMemoryTransaction

func NewInMemoryTransaction() *InMemoryTransaction

NewInMemoryTransaction returns a fresh, open transaction.

func (*InMemoryTransaction) Abort

func (t *InMemoryTransaction) Abort() error

Abort marks the transaction closed WITHOUT rolling back prior writes — see package doc. Idempotent with Commit in the sense that the first of the two wins and subsequent calls error.

func (*InMemoryTransaction) BoundSchemaTemplate

func (t *InMemoryTransaction) BoundSchemaTemplate() api.SchemaTemplate

BoundSchemaTemplate returns the bound template, or nil.

func (*InMemoryTransaction) Close

func (t *InMemoryTransaction) Close() error

Close is safe to call multiple times; only the first call transitions the state.

func (*InMemoryTransaction) Commit

func (t *InMemoryTransaction) Commit() error

Commit marks the transaction closed. The in-memory catalog applies writes eagerly, so Commit has no remaining work to do; it is the "closed" transition that matters to callers.

func (*InMemoryTransaction) IsClosed

func (t *InMemoryTransaction) IsClosed() bool

IsClosed reports whether the transaction has been Committed / Aborted / Closed.

func (*InMemoryTransaction) SetBoundSchemaTemplate

func (t *InMemoryTransaction) SetBoundSchemaTemplate(template api.SchemaTemplate)

SetBoundSchemaTemplate binds (or replaces) the template.

func (*InMemoryTransaction) UnsetBoundSchemaTemplate

func (t *InMemoryTransaction) UnsetBoundSchemaTemplate()

UnsetBoundSchemaTemplate clears any bound template.

func (*InMemoryTransaction) Unwrap

func (t *InMemoryTransaction) Unwrap() any

Unwrap returns the transaction itself because the in-memory catalog is the underlying storage backend. Satisfies api.Transaction.Unwrap.

type RecordLayerStoreCatalog

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

RecordLayerStoreCatalog is the FDB-backed api.StoreCatalog. Mirrors Java's com.apple.foundationdb.relational.recordlayer.catalog.RecordLayerStoreCatalog.

All methods open a fresh FDBRecordStore per call against the catalogSubspace, matching Java's pattern. Initialize marks the catalog store's state cacheable, as Java's does; the header flag is what a Java initialize reads, whether or not a Go state cache is configured.

Scope: schema + database CRUD, basic existence checks, ListSchemasInDatabase / ListDatabases. Schema template catalog lives in a sibling type returned from SchemaTemplateCatalog().

func NewRecordLayerStoreCatalog

func NewRecordLayerStoreCatalog(catalogSubspace subspace.Subspace) (*RecordLayerStoreCatalog, error)

NewRecordLayerStoreCatalog constructs the catalog rooted at the given __SYS/CATALOG subspace. Callers typically use OpenRecordLayerStoreCatalog() which bakes in the standard layout.

func OpenRecordLayerStoreCatalog

func OpenRecordLayerStoreCatalog() (*RecordLayerStoreCatalog, error)

OpenRecordLayerStoreCatalog uses the shared Java/Go catalog prefix. See DefaultCatalogSubspace for the byte-layout rationale.

func (*RecordLayerStoreCatalog) CreateDatabase

func (c *RecordLayerStoreCatalog) CreateDatabase(txn api.Transaction, dbURI string) error

CreateDatabase creates a Database row for dbURI. No-op if already present (matches Java's RecordLayerStoreCatalog — saveRecord is used directly, so a duplicate is overwritten silently; we mirror that).

func (*RecordLayerStoreCatalog) DeleteDatabase

func (c *RecordLayerStoreCatalog) DeleteDatabase(txn api.Transaction, dbURI string, throwIfDoesNotExist bool) (bool, error)

DeleteDatabase removes dbURI and every schema within it. Matches Java's RecordLayerStoreCatalog.deleteDatabase: scan-and-delete all Schemas rows with PK prefix [SCHEMA_TYPE_KEY, dbURI], then delete the Databases row. Returns (true, nil) on success, (false, nil) on timeout (Java returns false silently when TRANSACTION_INACTIVE/TIMEOUT; we surface other FDB errors). throwIfDoesNotExist=true raises ErrCodeUnknownDatabase when the db row is absent.

func (*RecordLayerStoreCatalog) DeleteSchema

func (c *RecordLayerStoreCatalog) DeleteSchema(txn api.Transaction, dbURI, schemaName string) error

DeleteSchema removes (dbURI, schemaName). Returns ErrCodeUndefinedSchema when the row is absent (matches Java).

func (*RecordLayerStoreCatalog) DoesDatabaseExist

func (c *RecordLayerStoreCatalog) DoesDatabaseExist(txn api.Transaction, dbURI string) (bool, error)

DoesDatabaseExist reports whether a Database row exists at dbURI.

func (*RecordLayerStoreCatalog) DoesSchemaExist

func (c *RecordLayerStoreCatalog) DoesSchemaExist(txn api.Transaction, dbURI, schemaName string) (bool, error)

DoesSchemaExist reports whether a Schema row exists at (dbURI, schemaName).

func (*RecordLayerStoreCatalog) Initialize

func (c *RecordLayerStoreCatalog) Initialize(txn api.Transaction) error

Initialize bootstraps the catalog schema's self-referential entries. It must be called once before the catalog is used, typically at service startup. Matches Java's RecordLayerStoreCatalog.initialize(txn):

  1. Marks the catalog store's state cacheable.
  2. Ensures the catalog schema template ("CATALOG_TEMPLATE") exists.
  3. Persists the catalog schema (/__SYS/CATALOG), creating the /__SYS database row if necessary, with ERROR_IF_DIFFERENT.

Java's initialize, in its order: open the catalog store and mark its state cacheable, create the catalog's template when no version of it is stored, then saveSchema(txn, catalogSchema, true, ERROR_IF_DIFFERENT), which writes nothing over an identical stored row, so concurrent initializations of an initialized catalog do not conflict, and refuses a row bound to a different template. Errors propagate as Java's do, with their own codes.

Idempotent: safe to call on every startup.

func (*RecordLayerStoreCatalog) ListDatabases

ListDatabases returns an api.ResultSet over every database. Materialises in-memory; continuation support is deferred. Uses a prefix scan keyed on [DATABASE_INFO_TYPE_KEY] matching Java's listDatabases TupleRange shape.

func (*RecordLayerStoreCatalog) ListSchemas

ListSchemas returns every schema in every database. Like ListDatabases, materialises in-memory; continuation is a follow-up.

func (*RecordLayerStoreCatalog) ListSchemasInDatabase

func (c *RecordLayerStoreCatalog) ListSchemasInDatabase(txn api.Transaction, databaseID string, _ api.Continuation) (api.ResultSet, error)

ListSchemasInDatabase narrows ListSchemas to a single database. An empty databaseID returns every schema (same as ListSchemas).

func (*RecordLayerStoreCatalog) LoadSchema

func (c *RecordLayerStoreCatalog) LoadSchema(txn api.Transaction, databaseID, schemaName string) (api.Schema, error)

LoadSchema loads (databaseID, schemaName) → api.Schema by deserialising the Schemas record, resolving its template via the SchemaTemplateCatalog, and materialising a Schema via template.GenerateSchema. Matches Java semantics: missing rows surface as ErrCodeUndefinedSchema regardless of whether the database or the schema was the missing bit (primary-key tuple lookup can't tell).

func (*RecordLayerStoreCatalog) RepairSchema

func (c *RecordLayerStoreCatalog) RepairSchema(txn api.Transaction, dbURI, schemaName string) error

RepairSchema rebinds schemaName in dbURI to the latest version of its owning template. Matches Java's repairSchema: load the schema with its template (refused when the bound version is gone), load the latest version, and save onto it with UPGRADE, a no-op when the schema is already on the latest version.

func (*RecordLayerStoreCatalog) RestoreTemplateVersion

func (c *RecordLayerStoreCatalog) RestoreTemplateVersion(ctx context.Context, db *recordlayer.FDBDatabase,
	ks *keyspace.RelationalKeyspace, name string, version int, md []byte,
) error

RestoreTemplateVersion restores a dropped template version from its stored MetaData bytes (md, the backup of the version's catalog META_DATA), for the schemas still bound to it, resolving their stores through ks, the keyspace the deployment opens its schemas with. It is fleet.RestoreTemplateVersion; every check above runs on every call. A refusal is 42F59 INVALID_SCHEMA_TEMPLATE, or 42F62 DUPLICATE_SCHEMA_TEMPLATE when the version is stored.

func (*RecordLayerStoreCatalog) SaveSchema

func (c *RecordLayerStoreCatalog) SaveSchema(txn api.Transaction, s api.Schema, createDatabaseIfNecessary bool, existsBehavior api.SchemaExistsBehavior) error

SaveSchema persists a Schema, in Java's saveSchema order: validate the schema; the database exists (created when createDatabaseIfNecessary, else UNDEFINED_DATABASE); the template exists at the schema's version (UNKNOWN_SCHEMA_TEMPLATE); load the stored row with its template, which fails when that template version is gone; existsBehavior decides a save over a stored row; write. A save that existsBehavior makes a no-op writes nothing, so it adds no write conflict range.

func (*RecordLayerStoreCatalog) SchemaTemplateCatalog

func (c *RecordLayerStoreCatalog) SchemaTemplateCatalog() api.SchemaTemplateCatalog

SchemaTemplateCatalog returns the template catalog sibling.

type RecordLayerStoreSchemaTemplateCatalog

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

RecordLayerStoreSchemaTemplateCatalog is the FDB-backed api.SchemaTemplateCatalog. Mirrors Java's RecordLayerStoreSchemaTemplateCatalog — versioned templates keyed by (templateName, templateVersion), with META_DATA holding the serialised RecordMetaData proto.

func (*RecordLayerStoreSchemaTemplateCatalog) CreateTemplate

func (c *RecordLayerStoreSchemaTemplateCatalog) CreateTemplate(txn api.Transaction, newTemplate api.SchemaTemplate) error

CreateTemplate persists a new (name, version), the one build-path writer of a template (DIVERGENCES.md "CreateTemplate refuses more than an exact duplicate, and carries a new version"). In order:

  • an existing (name, version) is refused with Java's text, "Schema template already exists" (ErrCodeDuplicateSchemaTemplate), Java's createTemplate's only refusal;
  • a version at or below the latest stored one is refused, and the relational evolution validator runs against that latest version (refuseBelowLatest; both a declared extension, section 9 (w));
  • the version guard (template_bindings.go): a schema bound to a dropped version above the latest refuses the save;
  • a new version of a stored template is carried from the latest stored version's bytes (carryTemplate: record-type keys, union numbers and indexes kept, the lane check over the indexes it defines, the evolution validator with index rebuilds allowed), and the carried bytes are what is written; a fresh name is lane-checked (checkIndexLanes) and written as built.

func (*RecordLayerStoreSchemaTemplateCatalog) DeleteTemplate

func (c *RecordLayerStoreSchemaTemplateCatalog) DeleteTemplate(txn api.Transaction, templateName string, throwIfDoesNotExist bool) error

DeleteTemplate removes ALL versions of templateName. When throwIfDoesNotExist is true, a missing template raises ErrCodeUnknownSchemaTemplate.

func (*RecordLayerStoreSchemaTemplateCatalog) DeleteTemplateVersion

func (c *RecordLayerStoreSchemaTemplateCatalog) DeleteTemplateVersion(txn api.Transaction, templateName string, version int, throwIfDoesNotExist bool) error

DeleteTemplateVersion removes one exact (name, version): Java's deleteTemplate(txn, name, version, throwIfDoesNotExist) (RecordLayerStoreSchemaTemplateCatalog.java:317-325), with its text.

A version a schema binds is not deleted (the version guard, template_bindings.go), where Java deletes the row regardless: deleting it would leave the schema bound to a version the catalog no longer has, which neither engine then loads, and which a later save could re-issue with other metadata. The refusal is a declared divergence (DIVERGENCES.md "DeleteTemplateVersion refuses a version schemas still bind; DROP SCHEMA TEMPLATE does not").

func (*RecordLayerStoreSchemaTemplateCatalog) DoesSchemaTemplateExist

func (c *RecordLayerStoreSchemaTemplateCatalog) DoesSchemaTemplateExist(txn api.Transaction, templateName string) (bool, error)

DoesSchemaTemplateExist reports whether any version of templateName exists.

func (*RecordLayerStoreSchemaTemplateCatalog) DoesSchemaTemplateExistAtVersion

func (c *RecordLayerStoreSchemaTemplateCatalog) DoesSchemaTemplateExistAtVersion(txn api.Transaction, templateName string, version int) (bool, error)

DoesSchemaTemplateExistAtVersion — exact (name, version) lookup.

func (*RecordLayerStoreSchemaTemplateCatalog) ListTemplates

ListTemplates enumerates every (name, version) row.

func (*RecordLayerStoreSchemaTemplateCatalog) LoadSchemaTemplate

func (c *RecordLayerStoreSchemaTemplateCatalog) LoadSchemaTemplate(txn api.Transaction, templateName string) (api.SchemaTemplate, error)

LoadSchemaTemplate loads the latest version of templateName. Matches Java: reverse scan, return first result. Errors with ErrCodeUnknownSchemaTemplate when no version exists.

func (*RecordLayerStoreSchemaTemplateCatalog) LoadSchemaTemplateAtVersion

func (c *RecordLayerStoreSchemaTemplateCatalog) LoadSchemaTemplateAtVersion(txn api.Transaction, templateName string, version int) (api.SchemaTemplate, error)

LoadSchemaTemplateAtVersion — exact version lookup.

func (*RecordLayerStoreSchemaTemplateCatalog) LoadTemplateProto

func (c *RecordLayerStoreSchemaTemplateCatalog) LoadTemplateProto(txn api.Transaction, templateName string, version int) (*gen.MetaData, error)

LoadTemplateProto returns the row's META_DATA unmarshalled, as stored.

type RelationalSchemaEvolutionValidator

type RelationalSchemaEvolutionValidator struct{}

RelationalSchemaEvolutionValidator validates that a new schema template version is backward-compatible with the current version stored in the catalog.

Rules (conservative by default — matches Java's relational evolution semantics):

  • Tables may be added; tables may NOT be removed.
  • For each existing table: columns may be added; columns may NOT be removed.
  • Column data types must not change (type widening is not yet implemented).
  • Primary key column order must not change (PKs are the first N columns in the StructDataType; we compare column names in declared order).

func NewRelationalSchemaEvolutionValidator

func NewRelationalSchemaEvolutionValidator() *RelationalSchemaEvolutionValidator

NewRelationalSchemaEvolutionValidator returns a validator with default (strict) settings.

func (*RelationalSchemaEvolutionValidator) Validate

func (v *RelationalSchemaEvolutionValidator) Validate(oldTemplate, newTemplate api.SchemaTemplate) error

Validate checks that newTemplate is backward-compatible with oldTemplate. Returns a non-nil error describing the first violation found.

type TemplateBinding

type TemplateBinding struct {
	DatabaseID, SchemaName string
}

TemplateBinding is a schema bound to a template version.

Jump to

Keyboard shortcuts

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