Documentation
¶
Index ¶
- Constants
- Variables
- func AutoFKName(childTable, parentTable string, columns []string) string
- func IsValidCondition(c Condition) bool
- func NewPager(file DBFile, pageSize, maxCachedPages int) (*pagerImpl, error)
- func PrimaryKeyName(tableName string) string
- func RecoverFromWAL(dbPath string, dbFile DBFile, pageSize uint32) (bool, error)
- func UniqueIndexName(tableName string, columns ...string) string
- func UnmarshalDatabaseHeader(buf []byte, dbHeader *DatabaseHeader) error
- func WithTransaction(ctx context.Context, tx *Transaction) context.Context
- type AggregateExpr
- type AggregateKind
- type ArithOp
- type BTreeIndex
- type CTE
- type CaseWhen
- type Cell
- type Column
- type ColumnKind
- type CompositeKey
- type Condition
- func FieldIsBetween(field Field, low, high any) Condition
- func FieldIsEqual(field Field, operandType OperandType, value any) Condition
- func FieldIsGreater(field Field, operandType OperandType, value any) Condition
- func FieldIsGreaterOrEqual(field Field, operandType OperandType, value any) Condition
- func FieldIsInAny(field Field, values ...any) Condition
- func FieldIsLess(field Field, operandType OperandType, value any) Condition
- func FieldIsLessOrEqual(field Field, operandType OperandType, value any) Condition
- func FieldIsLike(field Field, operandType OperandType, value any) Condition
- func FieldIsNotBetween(field Field, low, high any) Condition
- func FieldIsNotEqual(field Field, operandType OperandType, value any) Condition
- func FieldIsNotInAny(field Field, values ...any) Condition
- func FieldIsNotLike(field Field, operandType OperandType, value any) Condition
- func FieldIsNotNull(field Field) Condition
- func FieldIsNull(field Field) Condition
- type ConditionNode
- type Conditions
- type ConflictAction
- type Cursor
- type DBFile
- type DDLChanges
- func (d DDLChanges) CreatedIndex(tableName string, index SecondaryIndex) DDLChanges
- func (d DDLChanges) CreatedTable(t *Table) DDLChanges
- func (d DDLChanges) DroppedIndex(tableName string, index SecondaryIndex) DDLChanges
- func (d DDLChanges) DroppedTable(tableName string) DDLChanges
- func (d DDLChanges) HasChanges() bool
- type DDLSaver
- type Database
- func (d *Database) Analyze(ctx context.Context, target string) error
- func (d *Database) Checkpoint(_ context.Context) error
- func (d *Database) Close() error
- func (d *Database) ExecuteStatement(ctx context.Context, stmt Statement) (StatementResult, error)
- func (d *Database) GetDDLSaver() DDLSaver
- func (d *Database) GetFileName() string
- func (d *Database) GetSaver() PageSaver
- func (d *Database) GetTable(ctx context.Context, name string) (*Table, bool)
- func (d *Database) GetTransactionManager() *TransactionManager
- func (d *Database) IntegrityCheck(ctx context.Context) (IntegrityReport, error)
- func (d *Database) ListTableNames(ctx context.Context) []string
- func (d *Database) PrepareStatement(ctx context.Context, query string) (Statement, error)
- func (d *Database) PrepareStatements(ctx context.Context, sql string) ([]Statement, error)
- func (d *Database) QuickCheck(ctx context.Context) (IntegrityReport, error)
- func (d *Database) Reopen(ctx context.Context, factory PagerFactory, saver PageSaver) error
- func (d *Database) SaveDDLChanges(ctx context.Context, changes DDLChanges)
- func (d *Database) Vacuum(ctx context.Context) error
- type DatabaseHeader
- type DatabaseOption
- type Direction
- type ErrCheckConstraintViolation
- type ErrForeignKeyParentViolation
- type ErrForeignKeyViolation
- type ExcludedRef
- type Expr
- type FKAction
- type Field
- type Flusher
- type ForeignKey
- type FreePage
- type Function
- type Header
- type Histogram
- type ICell
- type Index
- func (ui *Index[T]) BFS(ctx context.Context, f indexCallback) error
- func (ui *Index[T]) Delete(ctx context.Context, keyAny any, rowID RowID) error
- func (ui *Index[T]) FindRowIDs(ctx context.Context, keyAny any) ([]RowID, error)
- func (ui *Index[T]) GetRootPageIdx() PageIndex
- func (ui *Index[T]) Insert(ctx context.Context, keyAny any, rowID RowID) error
- func (ui *Index[T]) ScanAll(ctx context.Context, reverse bool, callback indexScanner) error
- func (ui *Index[T]) ScanRange(ctx context.Context, rangeCondition RangeCondition, reverse bool, ...) error
- func (ui *Index[T]) Seek(ctx context.Context, page *Page, keyAny any) (IndexCursor[T], bool, error)
- func (ui *Index[T]) SeekLastKey(ctx context.Context, pageIdx PageIndex) (any, error)
- func (ui *Index[T]) SeekWithPrefix(ctx context.Context, page *Page, prefixAny any, prefixColumns int) (IndexCursor[T], bool, error)
- type IndexCell
- func (c *IndexCell[T]) Clone() IndexCell[T]
- func (c *IndexCell[T]) Marshal(buf []byte) error
- func (c *IndexCell[T]) RemoveRowID(id RowID) int
- func (c *IndexCell[T]) ReplaceRowID(id, newID RowID) int
- func (c *IndexCell[T]) Size() uint64
- func (c *IndexCell[T]) Unmarshal(columns []Column, buf []byte) (uint64, error)
- type IndexCursor
- type IndexInfo
- type IndexKey
- type IndexNode
- func (n *IndexNode[T]) AppendCells(cells ...IndexCell[T])
- func (n *IndexNode[T]) AtLeastHalfFull() bool
- func (n *IndexNode[T]) AvailableSpace() uint64
- func (n *IndexNode[T]) Child(childIdx uint32) (PageIndex, error)
- func (n *IndexNode[T]) Children() []PageIndex
- func (n *IndexNode[T]) Clone() *IndexNode[T]
- func (n *IndexNode[T]) DeleteKeyAndRightChild(idx uint32) error
- func (n *IndexNode[T]) FirstCell() IndexCell[T]
- func (n *IndexNode[T]) GetRightChildByIndex(idx uint32) PageIndex
- func (n *IndexNode[T]) HasSpaceForKey(key T) bool
- func (n *IndexNode[T]) Keys() []T
- func (n *IndexNode[T]) LastCell() IndexCell[T]
- func (n *IndexNode[T]) Marshal(buf []byte) error
- func (n *IndexNode[T]) MaxSpace() uint64
- func (n *IndexNode[T]) PrependCell(cell IndexCell[T])
- func (n *IndexNode[T]) RemoveFirstCell()
- func (n *IndexNode[T]) RemoveLastCell() IndexCell[T]
- func (n *IndexNode[T]) RowIDs() []RowID
- func (n *IndexNode[T]) SetChild(idx uint32, childPage PageIndex) error
- func (n *IndexNode[T]) Size() uint64
- func (n *IndexNode[T]) SplitInHalves(unique bool) (uint32, uint32)
- func (n *IndexNode[T]) TakenSpace() uint64
- func (n *IndexNode[T]) Unmarshal(columns []Column, buf []byte) (uint64, error)
- type IndexNodeHeader
- type IndexOverflowPage
- type IndexOverflowPageHeader
- type IndexStats
- type IntegrityIssue
- type IntegrityReport
- type InternalNode
- func (n *InternalNode) AppendCells(cells ...ICell)
- func (n *InternalNode) AtLeastHalfFull(maxIcells int) bool
- func (n *InternalNode) Child(childIdx uint32) (PageIndex, error)
- func (n *InternalNode) Children() []PageIndex
- func (n *InternalNode) Clone() *InternalNode
- func (n *InternalNode) DeleteKeyAndRightChild(idx uint32) error
- func (n *InternalNode) FirstCell() ICell
- func (n *InternalNode) GetRightChildByIndex(idx uint32) PageIndex
- func (n *InternalNode) IndexOfChild(key RowID) uint32
- func (n *InternalNode) IndexOfPage(pageIdx PageIndex) (uint32, error)
- func (n *InternalNode) Keys() []RowID
- func (n *InternalNode) LastCell() ICell
- func (n *InternalNode) Marshal(buf []byte) error
- func (n *InternalNode) MoreThanHalfFull(maxIcells int) bool
- func (n *InternalNode) PrependCell(cell ICell)
- func (n *InternalNode) RemoveFirstCell()
- func (n *InternalNode) RemoveLastCell()
- func (n *InternalNode) SetChild(idx uint32, childPage PageIndex) error
- func (n *InternalNode) Size() uint64
- func (n *InternalNode) Unmarshal(buf []byte) (uint64, error)
- type InternalNodeHeader
- type Interval
- type Iterator
- type Join
- type JoinAlgorithm
- type JoinColumnPair
- type JoinPlan
- type JoinType
- type LRUCache
- type LeafNode
- func (n *LeafNode) AppendCells(cells ...Cell)
- func (n *LeafNode) AtLeastHalfFull() bool
- func (n *LeafNode) AvailableSpace() uint64
- func (n *LeafNode) CanBorrowFirst() bool
- func (n *LeafNode) CanBorrowLast() bool
- func (n *LeafNode) CanMergeWith(n2 *LeafNode) bool
- func (n *LeafNode) Clone() *LeafNode
- func (n *LeafNode) DeepClone() *LeafNode
- func (n *LeafNode) Delete(key RowID) (Cell, bool)
- func (n *LeafNode) FirstCell() Cell
- func (n *LeafNode) HasSpaceForRow(row Row) bool
- func (n *LeafNode) Keys() []RowID
- func (n *LeafNode) LastCell() Cell
- func (n *LeafNode) Marshal(buf []byte) error
- func (n *LeafNode) MaxSpace() uint64
- func (n *LeafNode) PrepareModifyCell(idx uint32)
- func (n *LeafNode) PrependCell(cell Cell)
- func (n *LeafNode) RemoveFirstCell()
- func (n *LeafNode) RemoveLastCell()
- func (n *LeafNode) Size() uint64
- func (n *LeafNode) TakenSpace() uint64
- func (n *LeafNode) Unmarshal(columns []Column, buf []byte) (uint64, error)
- type LeafNodeHeader
- type LogicOp
- type OneOrMore
- type Operand
- type OperandType
- type Operator
- type OptionalValue
- type OrderBy
- type OverflowPage
- type OverflowPageHeader
- type Page
- type PageIndex
- type PageSaver
- type PageUnmarshaler
- type Pager
- type PagerFactory
- type Parser
- type Placeholder
- type PrimaryKey
- type QueryPlan
- type RangeBound
- type RangeCondition
- type Row
- func (r Row) CheckConditions(condGroup Conditions) (bool, error)
- func (r Row) CheckOneOrMore(conditions OneOrMore) (bool, error)
- func (r Row) CheckOneOrMoreWithColumnIndexes(conditions OneOrMore, columnIndexes map[string]int) (bool, error)
- func (r Row) Clone() Row
- func (r Row) GetColumn(name string) (Column, int)
- func (r Row) GetValue(name string) (OptionalValue, bool)
- func (r Row) GetValuesForColumns(columns []Column) ([]OptionalValue, bool)
- func (r Row) Marshal() ([]byte, error)
- func (r Row) NullBitmask() uint64
- func (r Row) OnlyFields(fields ...Field) Row
- func (r Row) SetValue(name string, value OptionalValue) (Row, bool)
- func (r Row) Size() uint64
- func (r Row) Unmarshal(cell Cell, selectedFields ...Field) (Row, error)
- func (r Row) UnmarshalWithMask(cell Cell, selectedMask []bool) (Row, error)
- type RowID
- type Scan
- type ScanType
- type Schema
- type SchemaType
- type SecondaryIndex
- type Statement
- func (s Statement) AddJoin(joinType JoinType, fromTableAlias, toTable, toTableAlias string, ...) (Statement, error)
- func (s Statement) BindArguments(args ...any) (Statement, error)
- func (s Statement) Clone() Statement
- func (s Statement) ColumnByName(name string) (Column, bool)
- func (s Statement) ColumnIdx(name string) int
- func (s Statement) DDL() string
- func (s Statement) HasField(name string) bool
- func (s Statement) InsertValuesForColumns(insertIdx int, columns ...Column) []OptionalValue
- func (s Statement) IsDDL() bool
- func (s Statement) IsSelectAggregate() bool
- func (s Statement) IsSelectAll() bool
- func (s Statement) IsSelectCountAll() bool
- func (s Statement) IsSelectGroupBy() bool
- func (s Statement) NumPlaceholders() int
- func (s Statement) Prepare(now Time) (Statement, error)
- func (s Statement) ReadOnly() bool
- func (s Statement) Validate(table *Table) error
- type StatementKind
- type StatementResult
- type Stats
- type SynchronousMode
- type Table
- func (t *Table) BFS(ctx context.Context, f callback) error
- func (t *Table) ColumnByName(name string) (Column, bool)
- func (t *Table) Delete(ctx context.Context, stmt Statement) (StatementResult, error)
- func (t *Table) DeleteKey(ctx context.Context, pageIdx PageIndex, key RowID) error
- func (t *Table) GetMaxKey(ctx context.Context, page *Page) (RowID, error)
- func (t *Table) GetRootPageIdx() PageIndex
- func (t *Table) HasIndexOnColumn(name string) bool
- func (t *Table) HasIndexOnColumns(columns []Column) bool
- func (t *Table) HasNoIndex() bool
- func (t *Table) HasPrimaryKey() bool
- func (t *Table) IndexByName(name string) (BTreeIndex, bool)
- func (t *Table) IndexColumnsByIndexName(name string) ([]Column, bool)
- func (t *Table) IndexInfoByColumnName(name string) (IndexInfo, bool)
- func (t *Table) IndexInfoByColumns(columns []Column) (IndexInfo, bool)
- func (t *Table) Insert(ctx context.Context, stmt Statement) (StatementResult, error)
- func (t *Table) InternalNodeInsert(ctx context.Context, parentPageIdx, childPageIdx PageIndex) error
- func (t *Table) InternalNodeSplitInsert(ctx context.Context, pageIdx, childPageIdx PageIndex) error
- func (t *Table) PlanQuery(ctx context.Context, stmt Statement) (QueryPlan, error)
- func (t *Table) RemoveSecondaryIndex(name string)
- func (t *Table) Seek(ctx context.Context, key RowID) (*Cursor, error)
- func (t *Table) SeekFirst(ctx context.Context) (*Cursor, error)
- func (t *Table) SeekLast(ctx context.Context, pageIdx PageIndex) (*Cursor, error)
- func (t *Table) SeekNextRowID(ctx context.Context, pageIdx PageIndex) (*Cursor, RowID, error)
- func (t *Table) Select(ctx context.Context, stmt Statement) (StatementResult, error)
- func (t *Table) SetSecondaryIndex(name string, columns []Column, index BTreeIndex)
- func (t *Table) Update(ctx context.Context, stmt Statement) (StatementResult, error)
- type TableOption
- func WithChildFKChecker(fn func(context.Context, Row) error) TableOption
- func WithForeignKeys(fks []ForeignKey) TableOption
- func WithParallelScan(enabled bool) TableOption
- func WithParentFKChecker(fn func(context.Context, Row) error) TableOption
- func WithParentFKUpdateEnforcer(fn func(context.Context, Row, Row) error) TableOption
- func WithPrimaryKey(pk PrimaryKey) TableOption
- func WithReferencedColumns(cols map[string]bool) TableOption
- func WithRowCountGetter(fn func() int64) TableOption
- func WithSecondaryIndex(index SecondaryIndex) TableOption
- func WithUniqueIndex(index UniqueIndex) TableOption
- type TableProvider
- type TextPointer
- func (tp TextPointer) IsEqual(tp2 TextPointer) bool
- func (tp TextPointer) IsInline() bool
- func (tp *TextPointer) Marshal(buf []byte, i uint64) error
- func (tp TextPointer) NumberOfPages() uint32
- func (tp TextPointer) Size() uint64
- func (tp TextPointer) String() string
- func (tp *TextPointer) Unmarshal(buf []byte, i uint64) error
- type Time
- type TimestampMicros
- type Transaction
- func (tx *Transaction) Abort()
- func (tx *Transaction) AddRowCountDelta(table string, delta int64)
- func (tx *Transaction) Commit()
- func (tx *Transaction) GetDBHeaderReadVersion() (uint64, bool)
- func (tx *Transaction) GetModifiedDBHeader() (*DatabaseHeader, bool)
- func (tx *Transaction) GetModifiedPage(pageIdx PageIndex) (*Page, bool)
- func (tx *Transaction) GetReadVersion(pageIdx PageIndex) (uint64, bool)
- func (tx *Transaction) GetReadVersions() map[PageIndex]uint64
- func (tx *Transaction) GetWriteVersions() map[PageIndex]WriteInfo
- func (tx *Transaction) RowCountDeltas() map[string]int64
- func (tx *Transaction) TrackDBHeaderRead(version uint64)
- func (tx *Transaction) TrackDBHeaderWrite(header DatabaseHeader)
- func (tx *Transaction) TrackRead(pageIdx PageIndex, version uint64)
- func (tx *Transaction) TrackWrite(pageIdx PageIndex, page, originalPage *Page, table, index string)
- type TransactionID
- type TransactionManager
- func (tm *TransactionManager) BeginReadOnlyTransaction(ctx context.Context) *Transaction
- func (tm *TransactionManager) BeginTransaction(ctx context.Context) *Transaction
- func (tm *TransactionManager) CheckpointWAL(dbFile DBFile) error
- func (tm *TransactionManager) CommitTransaction(ctx context.Context, tx *Transaction) error
- func (tm *TransactionManager) ExecuteInTransaction(ctx context.Context, fn func(ctx context.Context) error) error
- func (tm *TransactionManager) ExecuteReadOnlyTransaction(ctx context.Context, fn func(ctx context.Context) error) error
- func (tm *TransactionManager) GlobalDBHeaderVersion(ctx context.Context) uint64
- func (tm *TransactionManager) GlobalPageVersion(ctx context.Context, pageIdx PageIndex) uint64
- func (tm *TransactionManager) PageLastCommittedSeq(pageIdx PageIndex) uint64
- func (tm *TransactionManager) PageVersionAtSnapshot(pageIdx PageIndex, snapshotSeq uint64) (*Page, bool)
- func (tm *TransactionManager) RollbackTransaction(ctx context.Context, tx *Transaction)
- func (tm *TransactionManager) SetCheckpointFunc(fn func() error)
- func (tm *TransactionManager) SetRowCountApplier(fn func(map[string]int64))
- type TransactionStatus
- type TransactionalPager
- func (tp *TransactionalPager) AddFreePage(ctx context.Context, pageIdx PageIndex) error
- func (tp *TransactionalPager) GetFreePage(ctx context.Context) (*Page, error)
- func (tp *TransactionalPager) GetOverflowPage(ctx context.Context, pageIdx PageIndex) (*Page, error)
- func (tp *TransactionalPager) ModifyPage(ctx context.Context, pageIdx PageIndex) (*Page, error)
- func (tp *TransactionalPager) ReadPage(ctx context.Context, pageIdx PageIndex) (*Page, error)
- type TxPager
- type TxPagerFactory
- type UnionClause
- type UniqueIndex
- type WAL
- func (w *WAL) AppendTransaction(pages []WALPage) error
- func (w *WAL) Checkpoint(dbFile DBFile) error
- func (w *WAL) Close() error
- func (w *WAL) Delete() error
- func (w *WAL) Flush() error
- func (w *WAL) FrameCount() int64
- func (w *WAL) ReadAllFrames() ([]WALReadFrame, error)
- func (w *WAL) SetSynchronous(mode SynchronousMode)
- func (w *WAL) SetWriteBufferSize(n int)
- func (w *WAL) Synchronous() SynchronousMode
- func (w *WAL) Truncate() error
- type WALConfig
- type WALIndex
- func (wi *WALIndex) Has(pageIdx PageIndex) bool
- func (wi *WALIndex) Lookup(pageIdx PageIndex) ([]byte, bool)
- func (wi *WALIndex) MaxPageIndex() PageIndex
- func (wi *WALIndex) Rebuild(frames []WALReadFrame)
- func (wi *WALIndex) Reset()
- func (wi *WALIndex) Size() int
- func (wi *WALIndex) Update(pageIdx PageIndex, data []byte) []byte
- type WALPage
- type WALReadFrame
- type WriteInfo
- type WritePage
Constants ¶
const ( // DatabaseHeaderMagic identifies a MiniSQL database file. DatabaseHeaderMagic = "minisql\x00" // DatabaseFileFormatVersion identifies the current on-disk file header format. DatabaseFileFormatVersion = uint32(1) )
const ( // SchemaTableName is the internal table used to store schema metadata. SchemaTableName = "minisql_schema" // StatsTableName ... StatsTableName = "minisql_stats" // MaxColumns ... MaxColumns = 64 // RootPageConfigSize is the number of bytes reserved for the root page config header. RootPageConfigSize = 100 )
const ( // MaxInlineRowIDs ... MaxInlineRowIDs = 4 // MaxOverflowRowIDsPerPage ... MaxOverflowRowIDsPerPage = 510 // (4096 - 1 - 8 ) / 8 )
const ( // InternalNodeMaxCells is (4096 - 6 - 8) / 12. InternalNodeMaxCells = 340 // RootInternalNodeMaxCells is (4096 - 6 - 8 - 100) / 12. RootInternalNodeMaxCells = 331 )
InternalNode capacity constants derived from page and header sizes. Page size: 4096, Header size: 6 (base) + 8 (internal), ICell size: 12.
const ( // MaxInlineVarchar ... MaxInlineVarchar = 255 // Store up to 255 bytes inline // MaxOverflowPageData ... MaxOverflowPageData = 4096 - 1 - 8 // Page size - page type byte - OverflowPageHeader size // MaxOverflowTextSize limits the maximum size of a text value to 16 overflow pages. MaxOverflowTextSize = MaxOverflowPageData * 16 )
const ( // PageSize ... PageSize = 4096 // 4 kilobytes // UsablePageSize returns the usable size of a page after accounting for headers // Page size minus base + internal/leaf header, minus key and null bitmask UsablePageSize = PageSize - 7 - 8 - 8 - 8 )
const ( // PageTypeLeaf ... PageTypeLeaf byte = iota // PageTypeInternal identifies an internal (non-leaf) B+ tree node page. PageTypeInternal // PageTypeOverflow identifies a text overflow page. PageTypeOverflow // PageTypeIndex identifies an index B+ tree node page. PageTypeIndex // PageTypeFree identifies a free (unused) page available for reuse. PageTypeFree // PageTypeIndexOverflow identifies an index overflow page for large row ID lists. PageTypeIndexOverflow )
PageType constants identify the type of data stored in a database page.
const ( // WALMagic is the 8-byte magic string at the start of every WAL file. WALMagic = "miniwal\n" // WALVersion is the current on-disk WAL format version. WALVersion = uint32(1) // WALFileHeaderSize is the fixed byte size of the WAL file header. WALFileHeaderSize = 32 // WALFrameHeaderSize is the fixed byte size of each WAL frame header. WALFrameHeaderSize = 24 )
WAL file-format constants.
const ICellSize = 12 // (8+4)
ICellSize is the serialised byte size of an ICell (8-byte key + 4-byte child pointer).
const MaxIndexKeySize = 255
MaxIndexKeySize is the maximum number of bytes allowed for a single index key.
const PageCacheSize = 2000
PageCacheSize is the default maximum number of pages to keep in memory.
const RightChildNotSet = math.MaxUint32
RightChildNotSet is the sentinel value indicating an internal node has no right child yet.
Variables ¶
var ErrCheckpointBlockedByReaders = errors.New("checkpoint blocked: active snapshot readers")
ErrCheckpointBlockedByReaders is returned when a checkpoint cannot proceed because one or more read-only transactions hold snapshots that predate the current commitSeq. Callers should retry after the readers have finished.
var ErrDropTableReferencedByFK = errors.New("cannot drop table: it is still referenced by a foreign key constraint")
ErrDropTableReferencedByFK is the base error for dropping a table that is still referenced by a foreign key in another table.
var ErrDuplicateKey = errors.New("duplicate key")
ErrDuplicateKey ...
var ErrNoMoreRows = errors.New("no more rows")
ErrNoMoreRows ...
var ErrNotFound = errors.New("not found")
ErrNotFound ...
var ErrNotWALMode = errors.New("WAL mode is not enabled")
ErrNotWALMode is returned when a WAL-specific operation is called on a transaction manager that is not in WAL mode.
var ErrTxConflict = errors.New("transaction conflict detected")
ErrTxConflict is returned when an optimistic concurrency check fails at commit time.
var FunctionNow = Function{Name: nowFunctionName}
FunctionNow ...
var ( // MainTableSQL is the DDL used to create the internal schema metadata table. MainTableSQL = fmt.Sprintf(`create table "%s" ( type int4 not null, name varchar(255) not null, tbl_name varchar(255), root_page int4 not null, sql text );`, SchemaTableName) )
var ( // StatsTableSQL is the DDL used to create the internal statistics table. StatsTableSQL = fmt.Sprintf(`create table "%s" ( tbl varchar(255), idx varchar(255), stat text );`, StatsTableName) )
Functions ¶
func AutoFKName ¶ added in v0.52.0
AutoFKName builds a deterministic FK constraint name from the involved tables and columns.
func IsValidCondition ¶
IsValidCondition checks that all fields of the condition are set
func NewPager ¶
NewPager opens the database file and initialises the pager. maxCachedPages sets the maximum number of pages to keep in cache (0 = use default).
func RecoverFromWAL ¶ added in v0.12.0
RecoverFromWAL checks for a WAL file at dbPath+"-wal" and, if found, replays all committed frames into dbFile. The WAL is truncated on success. Returns true when recovery was performed.
func UniqueIndexName ¶
UniqueIndexName ...
func UnmarshalDatabaseHeader ¶
func UnmarshalDatabaseHeader(buf []byte, dbHeader *DatabaseHeader) error
UnmarshalDatabaseHeader deserialises a database header from the given byte slice.
func WithTransaction ¶
func WithTransaction(ctx context.Context, tx *Transaction) context.Context
WithTransaction stores a transaction in the context and returns the new context.
Types ¶
type AggregateExpr ¶
type AggregateExpr struct {
Column string
Kind AggregateKind
}
AggregateExpr describes a single aggregate function call in a SELECT list. Parallel to Fields: Fields[i] holds the synthetic output column name (e.g. "SUM(price)"), Aggregates[i] holds the kind and source column. A zero-value AggregateExpr (Kind == 0) means the corresponding field is not an aggregate. Aggregates is only populated when the query contains at least one aggregate function.
type AggregateKind ¶
type AggregateKind int
AggregateKind identifies the type of aggregate function.
const ( // AggregateCount ... AggregateCount AggregateKind = iota + 1 // COUNT(*) // AggregateSum ... AggregateSum // SUM(col) // AggregateAvg is the AVG aggregate function. AggregateAvg // AVG(col) // AggregateMin is the MIN aggregate function. AggregateMin // MIN(col) // AggregateMax is the MAX aggregate function. AggregateMax // MAX(col) )
AggregateKind constants enumerate the supported aggregate functions.
func (AggregateKind) String ¶
func (k AggregateKind) String() string
type ArithOp ¶ added in v0.4.0
type ArithOp int
ArithOp identifies the arithmetic operator in a binary Expr node.
ArithOp constants.
type BTreeIndex ¶
type BTreeIndex interface {
GetRootPageIdx() PageIndex
FindRowIDs(ctx context.Context, key any) ([]RowID, error)
SeekLastKey(ctx context.Context, pageIdx PageIndex) (any, error)
Insert(ctx context.Context, key any, rowID RowID) error
Delete(ctx context.Context, key any, rowID RowID) error
ScanAll(ctx context.Context, reverse bool, callback indexScanner) error
ScanRange(ctx context.Context, rangeCondition RangeCondition, reverse bool, callback indexScanner) error
BFS(ctx context.Context, f indexCallback) error
}
BTreeIndex ...
type CaseWhen ¶ added in v0.8.0
type CaseWhen struct {
Cond *ConditionNode // searched CASE: WHEN <condition>
When *Expr // simple CASE: WHEN <value> (compared to parent CaseInput)
Then *Expr // THEN <result>
}
CaseWhen holds one WHEN/THEN branch of a CASE expression. Exactly one of Cond (searched CASE) or When (simple CASE) is set.
type Cell ¶
type Cell struct {
Value []byte
NullBitmask uint64
Key RowID
// contains filtered or unexported fields
}
Cell ...
type Column ¶
type Column struct {
DefaultValue OptionalValue
CheckCond *ConditionNode // parsed CHECK expression (nil if no CHECK constraint)
Name string
Check string // raw SQL text of CHECK expression, e.g. "age > 0"
Kind ColumnKind
Size uint32
Nullable bool
DefaultValueNow bool
}
Column ...
type ColumnKind ¶
type ColumnKind int
ColumnKind ...
const ( // Boolean ... Boolean ColumnKind = iota + 1 Int4 Int8 Real Double Varchar Text Timestamp )
ColumnKind constants enumerate the supported column data types.
func (ColumnKind) String ¶
func (k ColumnKind) String() string
type CompositeKey ¶
type CompositeKey struct {
Columns []Column
Values []any
// Store the binary representation for comparison (excludes length prefixes for varchars)
Comparison []byte
}
CompositeKey holds the column definitions and values for a multi-column index key.
func NewCompositeKey ¶
func NewCompositeKey(columns []Column, values ...any) CompositeKey
NewCompositeKey constructs a CompositeKey from the given columns and values.
func (*CompositeKey) Marshal ¶
func (ck *CompositeKey) Marshal(buf []byte, i uint64) error
Marshal serialises the composite key into buf starting at offset i.
func (CompositeKey) Prefix ¶
func (ck CompositeKey) Prefix(columns int) CompositeKey
Prefix returns a CompositeKey containing only the first n columns' comparison bytes.
func (CompositeKey) Size ¶
func (ck CompositeKey) Size() uint64
Size returns the serialised byte size of the composite key.
type Condition ¶
Condition represents a single predicate: operand1 operator operand2.
func FieldIsBetween ¶
FieldIsBetween creates a field BETWEEN low AND high condition.
func FieldIsEqual ¶
func FieldIsEqual(field Field, operandType OperandType, value any) Condition
FieldIsEqual creates a field = value condition.
func FieldIsGreater ¶
func FieldIsGreater(field Field, operandType OperandType, value any) Condition
FieldIsGreater creates a field > value condition.
func FieldIsGreaterOrEqual ¶
func FieldIsGreaterOrEqual(field Field, operandType OperandType, value any) Condition
FieldIsGreaterOrEqual creates a field >= value condition.
func FieldIsInAny ¶
FieldIsInAny creates a field IN (values...) condition.
func FieldIsLess ¶
func FieldIsLess(field Field, operandType OperandType, value any) Condition
FieldIsLess creates a field < value condition.
func FieldIsLessOrEqual ¶
func FieldIsLessOrEqual(field Field, operandType OperandType, value any) Condition
FieldIsLessOrEqual creates a field <= value condition.
func FieldIsLike ¶
func FieldIsLike(field Field, operandType OperandType, value any) Condition
FieldIsLike creates a field LIKE value condition.
func FieldIsNotBetween ¶
FieldIsNotBetween creates a field NOT BETWEEN low AND high condition.
func FieldIsNotEqual ¶
func FieldIsNotEqual(field Field, operandType OperandType, value any) Condition
FieldIsNotEqual creates a field != value condition.
func FieldIsNotInAny ¶
FieldIsNotInAny creates a field NOT IN (values...) condition.
func FieldIsNotLike ¶
func FieldIsNotLike(field Field, operandType OperandType, value any) Condition
FieldIsNotLike creates a field NOT LIKE value condition.
func FieldIsNotNull ¶
FieldIsNotNull creates a field IS NOT NULL condition.
func FieldIsNull ¶
FieldIsNull creates a field IS NULL condition.
type ConditionNode ¶
type ConditionNode struct {
Leaf *Condition
Left *ConditionNode
Right *ConditionNode
Op LogicOp
}
ConditionNode is a node in a boolean expression tree for WHERE clauses. Leaf nodes (Leaf != nil) hold a single Condition. Branch nodes (Left != nil) join two sub-expressions with a logical operator.
func (*ConditionNode) Columns ¶ added in v0.8.0
func (n *ConditionNode) Columns() []string
Columns returns all column names referenced in the condition tree.
func (*ConditionNode) IsLeaf ¶
func (n *ConditionNode) IsLeaf() bool
IsLeaf returns true if this is a leaf node.
func (*ConditionNode) String ¶ added in v0.8.0
func (n *ConditionNode) String() string
String returns a human-readable representation of the condition tree, used as a fallback column name for CASE expressions without AS aliases.
func (*ConditionNode) ToDNF ¶
func (n *ConditionNode) ToDNF() OneOrMore
ToDNF converts the condition tree to Disjunctive Normal Form. The result is a OneOrMore where each Conditions group is a conjunction (conditions ANDed together) and the outer slice is a disjunction (groups ORed). This allows arbitrary WHERE nesting to be evaluated by existing row filtering code.
type Conditions ¶
type Conditions []Condition
Conditions is a slice of Condition values joined by AND within a single OR group.
type ConflictAction ¶
type ConflictAction int
ConflictAction describes what to do when an INSERT violates a uniqueness constraint.
const ( // ConflictActionNone is the default: propagate the error. ConflictActionNone ConflictAction = iota // ConflictActionDoNothing silently skips the offending row. ConflictActionDoNothing // ConflictActionDoUpdate applies the SET assignments to the conflicting row. ConflictActionDoUpdate )
type Cursor ¶
Cursor is a position within a table's B+ tree used to traverse or modify rows.
func (*Cursor) LeafNodeInsert ¶
LeafNodeInsert inserts a row at the cursor's current position, splitting the leaf node if necessary.
type DDLChanges ¶
type DDLChanges struct {
CreateIndexes map[string]SecondaryIndex
DropIndexes map[string]SecondaryIndex
CreateTables []*Table
DropTables []string
}
DDLChanges accumulates schema modifications made within a single transaction.
func (DDLChanges) CreatedIndex ¶
func (d DDLChanges) CreatedIndex(tableName string, index SecondaryIndex) DDLChanges
CreatedIndex records an index creation in the DDL change set.
func (DDLChanges) CreatedTable ¶
func (d DDLChanges) CreatedTable(t *Table) DDLChanges
CreatedTable records a table creation in the DDL change set.
func (DDLChanges) DroppedIndex ¶
func (d DDLChanges) DroppedIndex(tableName string, index SecondaryIndex) DDLChanges
DroppedIndex records an index drop in the DDL change set.
func (DDLChanges) DroppedTable ¶
func (d DDLChanges) DroppedTable(tableName string) DDLChanges
DroppedTable records a table drop in the DDL change set.
func (DDLChanges) HasChanges ¶
func (d DDLChanges) HasChanges() bool
HasChanges reports whether there are any uncommitted DDL changes.
type DDLSaver ¶
type DDLSaver interface {
SaveDDLChanges(ctx context.Context, changes DDLChanges)
}
DDLSaver ...
type Database ¶
type Database struct {
// contains filtered or unexported fields
}
Database is the top-level embedded SQL database instance.
func NewDatabase ¶
func NewDatabase(ctx context.Context, logger *zap.Logger, dbFilePath string, parser Parser, factory PagerFactory, saver PageSaver, walCfg *WALConfig, opts ...DatabaseOption) (*Database, error)
NewDatabase creates a new database. walCfg wires in the Write-Ahead Log; pass nil for in-memory/test databases that do not require WAL (commits fall back to writing directly to the pager).
func (*Database) Analyze ¶
Analyze gathers statistics for all tables (or a specific target) and stores them in the stats table.
func (*Database) Checkpoint ¶ added in v0.12.0
Checkpoint checkpoints the WAL into the database file and truncates the WAL. It is a no-op when no WAL is configured.
Checkpoint blocks new WAL writers until it completes. Readers are not blocked: they continue to use the (now being reset) WAL index, which is fine because the pager cache still holds the correct pages and the DB file is being written with the same data.
func (*Database) ExecuteStatement ¶
ExecuteStatement executes a single statement and returns the result
func (*Database) GetDDLSaver ¶
GetDDLSaver returns the DDLSaver interface backed by this database.
func (*Database) GetFileName ¶
GetFileName returns the database file name
func (*Database) GetTable ¶
GetTable retrieves a table by name in a thread-safe manner. CTE virtual tables registered in the context shadow real tables of the same name.
func (*Database) GetTransactionManager ¶
func (d *Database) GetTransactionManager() *TransactionManager
GetTransactionManager returns the transaction manager for this database
func (*Database) IntegrityCheck ¶ added in v0.5.0
func (d *Database) IntegrityCheck(ctx context.Context) (IntegrityReport, error)
IntegrityCheck performs a deeper structural walk of the database file.
In addition to QuickCheck, it traverses reachable table, index, and overflow pages from schema roots, reports orphan pages, and flags pages that appear in both live structures and the free list.
func (*Database) ListTableNames ¶
ListTableNames lists names of all tables in the database
func (*Database) PrepareStatement ¶
PrepareStatement parses and caches a SQL statement, returning the parsed Statement.
func (*Database) PrepareStatements ¶
PrepareStatements parses SQL into a slice of Statement struct
func (*Database) QuickCheck ¶ added in v0.4.0
func (d *Database) QuickCheck(ctx context.Context) (IntegrityReport, error)
QuickCheck performs a cheap structural health check of the open database.
It validates header-linked free-list metadata and the decodability/shape of table and index root pages, but it does not walk full B-tree contents or cross-check tables against indexes.
func (*Database) Reopen ¶
Reopen replaces the pager and transaction manager with fresh instances backed by the given factory and saver.
func (*Database) SaveDDLChanges ¶
func (d *Database) SaveDDLChanges(ctx context.Context, changes DDLChanges)
SaveDDLChanges applies committed DDL changes (table/index creates and drops) to the in-memory schema.
func (*Database) Vacuum ¶
Vacuum compacts the database file by copying all live data into a fresh file, then atomically replacing the original. The algorithm is:
- Create a temporary database file with its own pager.
- Acquire the exclusive database write lock, blocking all concurrent reads and writes for the duration.
- Recreate every table schema (tables first, indexes second) in the temp DB.
- Copy every row from the live DB into the temp DB.
- Flush and close both the temp DB and the live DB.
- Safe atomic file swap: a. Rename live → live.bak b. Rename temp → live (on failure, restore live from live.bak) c. Remove live.bak
- Reopen the database with a fresh pager and transaction manager.
Crash-safety: if the process crashes between steps 6a and 6b the original data is intact in live.bak. On restart the caller should check for a live.bak file and rename it back if the expected database file is missing.
VACUUM must not be called from inside an explicit user transaction; doing so returns an error.
type DatabaseHeader ¶
type DatabaseHeader struct {
FirstFreePage PageIndex // Points to first free page, 0 if none
FreePageCount uint32 // Number of free pages available
}
DatabaseHeader stores the global database state persisted at the start of the first page.
func (*DatabaseHeader) Marshal ¶
func (h *DatabaseHeader) Marshal() ([]byte, error)
Marshal serialises the database header to a byte slice.
func (*DatabaseHeader) Size ¶
func (h *DatabaseHeader) Size() uint64
Size returns the fixed serialised byte size of the database header.
type DatabaseOption ¶
type DatabaseOption func(*Database)
DatabaseOption is a functional option for configuring a Database.
func WithMaxCachedStatements ¶
func WithMaxCachedStatements(maxStatements int) DatabaseOption
WithMaxCachedStatements configures the maximum number of prepared statements to keep in the LRU cache.
func WithParallelScanEnabled ¶ added in v0.51.0
func WithParallelScanEnabled() DatabaseOption
WithParallelScanEnabled turns on concurrent leaf-page scanning for all user tables.
type Direction ¶
type Direction int
Direction ...
Direction constants define the sort order for ORDER BY clauses.
type ErrCheckConstraintViolation ¶ added in v0.41.0
ErrCheckConstraintViolation is returned when an INSERT or UPDATE row fails a CHECK constraint.
func (ErrCheckConstraintViolation) Error ¶ added in v0.41.0
func (e ErrCheckConstraintViolation) Error() string
type ErrForeignKeyParentViolation ¶ added in v0.52.0
type ErrForeignKeyParentViolation struct {
ParentTable string
ParentColumns []string
ChildTable string
ChildColumns []string
}
ErrForeignKeyParentViolation is returned when deleting or updating a parent row that is still referenced by one or more child rows.
func (ErrForeignKeyParentViolation) Error ¶ added in v0.52.0
func (e ErrForeignKeyParentViolation) Error() string
type ErrForeignKeyViolation ¶ added in v0.52.0
type ErrForeignKeyViolation struct {
ChildTable string
ChildColumns []string
ParentTable string
ParentColumns []string
}
ErrForeignKeyViolation is returned when a child row's FK value does not exist in the parent table.
func (ErrForeignKeyViolation) Error ¶ added in v0.52.0
func (e ErrForeignKeyViolation) Error() string
type ExcludedRef ¶ added in v0.2.0
type ExcludedRef struct {
Column string
}
ExcludedRef represents a reference to EXCLUDED.column_name inside an ON CONFLICT DO UPDATE SET clause. At upsert time it resolves to the value that was proposed for insertion but rejected due to the conflict.
type Expr ¶ added in v0.4.0
type Expr struct {
Literal any
Right *Expr
CaseElse *Expr
CaseInput *Expr
Left *Expr
CastExpr *Expr
FuncName string
Column string
Args []*Expr
CaseClauses []CaseWhen
CastTargetType ColumnKind
Op ArithOp
IsNull bool
}
Expr is an arithmetic expression tree node. Exactly one interpretation is active (checked in priority order):
- CaseClauses != nil: a CASE WHEN expression
- FuncName != "": a built-in function call (Args holds the arguments)
- CastExpr != nil: a CAST(expr AS type) expression
- IsNull: an explicit NULL literal
- Column != "": a column reference (read value from the row)
- Literal != nil: a scalar literal (int64, float64, bool, TextPointer)
- Left != nil && Op != 0: a binary arithmetic operation
func (*Expr) Columns ¶ added in v0.4.0
Columns returns all column names referenced by this expression.
func (*Expr) Eval ¶ added in v0.4.0
Eval evaluates the expression against a row, returning a numeric result. NULL propagates: any NULL operand produces a nil result. Returns int64 when both operands are int64 (except division, which always returns float64). Returns float64 when either operand is float64.
type FKAction ¶ added in v0.52.0
type FKAction int
FKAction defines the referential action for ON DELETE / ON UPDATE.
const ( // FKActionRestrict rejects the operation if it would break the FK constraint. FKActionRestrict FKAction = iota + 1 // FKActionNoAction is the same as RESTRICT in this implementation (no deferred checks). FKActionNoAction // FKActionSetNull sets the FK column(s) to NULL when the referenced row is deleted/updated. FKActionSetNull // FKActionCascade propagates the delete/update to child rows. FKActionCascade )
type Field ¶
Field ...
func (Field) OutputName ¶ added in v0.4.0
OutputName returns the name to use for this field in result column metadata. For computed expressions it returns the Alias (if set) or the expression string.
type Flusher ¶
type Flusher interface {
TotalPages() uint32
Flush(context.Context, PageIndex) error
FlushBatch(context.Context, []PageIndex) error
Close() error
}
Flusher ...
type ForeignKey ¶ added in v0.52.0
type ForeignKey struct {
Name string
Columns []string // local (child) columns
TargetTable string // referenced (parent) table
TargetColumns []string // referenced columns in parent table
OnDelete FKAction // default FKActionRestrict
OnUpdate FKAction // default FKActionRestrict
}
ForeignKey describes a FOREIGN KEY constraint on one or more child table columns.
type FreePage ¶
type FreePage struct {
NextFreePage PageIndex // Points to next free page, 0 if last
}
FreePage reuses the existing page structure for tracking free (unused) pages.
type Histogram ¶ added in v0.50.0
type Histogram struct {
Bounds []float64
}
Histogram is an equi-depth histogram for a numeric index column. Bounds contains numBuckets+1 boundary values: Bounds[0] is the minimum observed value, Bounds[N] is the maximum. Each of the N buckets between consecutive boundaries holds approximately the same number of entries.
type Index ¶
type Index[T IndexKey] struct { Name string Columns []Column // contains filtered or unexported fields }
Index ...
func NewNonUniqueIndex ¶
func NewNonUniqueIndex[T IndexKey](logger *zap.Logger, txManager *TransactionManager, name string, columns []Column, pager TxPager, rootPageIdx PageIndex) (*Index[T], error)
NewNonUniqueIndex ...
func NewUniqueIndex ¶
func NewUniqueIndex[T IndexKey](logger *zap.Logger, txManager *TransactionManager, name string, columns []Column, pager TxPager, rootPageIdx PageIndex) (*Index[T], error)
NewUniqueIndex ...
func (*Index[T]) FindRowIDs ¶
FindRowIDs ...
func (*Index[T]) ScanAll ¶
ScanAll iterates over all keys in the index in order using in-order traversal
func (*Index[T]) ScanRange ¶
func (ui *Index[T]) ScanRange(ctx context.Context, rangeCondition RangeCondition, reverse bool, callback indexScanner) error
ScanRange scans keys within the specified range using in-order traversal with range checks.
func (*Index[T]) SeekLastKey ¶
SeekLastKey returns the largest key in the index, used for autoincrement primary keys.
type IndexCell ¶
type IndexCell[T IndexKey] struct { Key T RowIDs []RowID UniqueRowID RowID InlineRowIDs uint32 Overflow PageIndex Child PageIndex // contains filtered or unexported fields }
IndexCell holds a single key entry within an index node, along with its associated row IDs and child pointer.
func (*IndexCell[T]) ReplaceRowID ¶
ReplaceRowID ...
type IndexCursor ¶
IndexCursor holds a position within an index, grouping page and cell index. TODO - currently this struct has no methods; consider merging into Index or adding useful methods.
type IndexNode ¶
type IndexNode[T IndexKey] struct { Cells []IndexCell[T] Header IndexNodeHeader // contains filtered or unexported fields }
IndexNode is a B+ tree node used by the index, containing a header and a slice of index cells.
func NewIndexNode ¶
NewIndexNode creates a new IndexNode with the given uniqueness flag and optional initial cells.
func NewRootIndexNode ¶
NewRootIndexNode ...
func (*IndexNode[T]) AppendCells ¶
AppendCells ...
func (*IndexNode[T]) AtLeastHalfFull ¶
AtLeastHalfFull ...
func (*IndexNode[T]) AvailableSpace ¶
AvailableSpace returns the number of free bytes in this node (O(1) via cached freeBytes).
func (*IndexNode[T]) Child ¶
Child returns a node index of nth child of the node marked by its index (0 for the leftmost child, index equal to number of keys means the rightmost child).
func (*IndexNode[T]) DeleteKeyAndRightChild ¶
DeleteKeyAndRightChild removes the key at idx plus the right child pointer from the index node.
func (*IndexNode[T]) GetRightChildByIndex ¶
GetRightChildByIndex ...
func (*IndexNode[T]) HasSpaceForKey ¶
HasSpaceForKey ...
func (*IndexNode[T]) PrependCell ¶
PrependCell ...
func (*IndexNode[T]) RemoveLastCell ¶
RemoveLastCell ...
func (*IndexNode[T]) RowIDs ¶
RowIDs returns inlined row IDs; there could be more row IDs in overflow pages, so keep that in mind when working with non-unique indexes.
func (*IndexNode[T]) SplitInHalves ¶
SplitInHalves ...
type IndexNodeHeader ¶
type IndexNodeHeader struct {
IsRoot bool
IsLeaf bool
Parent PageIndex
Keys uint32
RightChild PageIndex
}
IndexNodeHeader ...
type IndexOverflowPage ¶
type IndexOverflowPage struct {
RowIDs []RowID
Header IndexOverflowPageHeader
}
IndexOverflowPage ...
func (*IndexOverflowPage) Marshal ¶
func (h *IndexOverflowPage) Marshal(buf []byte) error
Marshal ...
func (*IndexOverflowPage) RemoveLastRowID ¶
func (h *IndexOverflowPage) RemoveLastRowID() RowID
RemoveLastRowID ...
func (*IndexOverflowPage) Unmarshal ¶
func (h *IndexOverflowPage) Unmarshal(buf []byte) error
Unmarshal ...
type IndexOverflowPageHeader ¶
type IndexOverflowPageHeader struct {
NextPage PageIndex // 0 if last page
ItemCount uint32 // how many row IDs are stored in this page
}
IndexOverflowPageHeader ...
type IndexStats ¶
type IndexStats struct {
NDistinct []int64
NEntry int64
Hist *Histogram // nil when not collected or column type is non-numeric
}
IndexStats holds parsed statistics for an index
func (IndexStats) EstimateRangeRows ¶
func (s IndexStats) EstimateRangeRows(rangeCondition RangeCondition, columnIndex int) int64
EstimateRangeRows estimates the number of rows that will match a range condition. Returns the estimated row count, or -1 if estimation isn't possible. Uses histogram data when available, otherwise assumes uniform distribution.
func (IndexStats) Selectivity ¶
func (s IndexStats) Selectivity() float64
Selectivity returns the selectivity of the index (0.0 to 1.0) Higher selectivity means more distinct values relative to total entries For composite indexes, uses the final column prefix
type IntegrityIssue ¶ added in v0.4.0
IntegrityIssue represents a single integrity problem discovered by a check.
type IntegrityReport ¶ added in v0.4.0
type IntegrityReport struct {
Issues []IntegrityIssue
CheckedRootPages int
CheckedFreePages int
CheckedLivePages int
TotalPages uint32
FreeListPageCount uint32
}
IntegrityReport summarises the result of an integrity check.
func (IntegrityReport) Ok ¶ added in v0.4.0
func (r IntegrityReport) Ok() bool
Ok returns true when the integrity check found no issues.
type InternalNode ¶
type InternalNode struct {
Header InternalNodeHeader
ICells [InternalNodeMaxCells]ICell
}
InternalNode ...
func (*InternalNode) AppendCells ¶
func (n *InternalNode) AppendCells(cells ...ICell)
AppendCells ...
func (*InternalNode) AtLeastHalfFull ¶
func (n *InternalNode) AtLeastHalfFull(maxIcells int) bool
AtLeastHalfFull ...
func (*InternalNode) Child ¶
func (n *InternalNode) Child(childIdx uint32) (PageIndex, error)
Child returns a node index of nth child of the node marked by its index (0 for the leftmost child, index equal to number of keys means the rightmost child).
func (*InternalNode) DeleteKeyAndRightChild ¶
func (n *InternalNode) DeleteKeyAndRightChild(idx uint32) error
DeleteKeyAndRightChild removes the key at idx plus the right child pointer from the internal node.
func (*InternalNode) GetRightChildByIndex ¶
func (n *InternalNode) GetRightChildByIndex(idx uint32) PageIndex
GetRightChildByIndex ...
func (*InternalNode) IndexOfChild ¶
func (n *InternalNode) IndexOfChild(key RowID) uint32
IndexOfChild returns the index of the child which should contain the given key. For example, if node has 2 keys, this could return 0 for the leftmost child, 1 for the middle child or 2 for the rightmost child. The returned value is not a node index!
func (*InternalNode) IndexOfPage ¶
func (n *InternalNode) IndexOfPage(pageIdx PageIndex) (uint32, error)
IndexOfPage returns index of child which contains page number
func (*InternalNode) MoreThanHalfFull ¶
func (n *InternalNode) MoreThanHalfFull(maxIcells int) bool
MoreThanHalfFull ...
type InternalNodeHeader ¶
InternalNodeHeader ...
type Interval ¶ added in v0.11.0
type Interval struct {
Months int32 // total months component (years×12 + months)
Micros int64 // fixed-duration component in microseconds
}
Interval represents a SQL interval with two components:
- Months: calendar months (years×12 + months); variable-length because a month contains a different number of days depending on which month it is.
- Micros: fixed-duration part in microseconds (weeks×7×86400×1e6 + days×86400×1e6 + …).
Separating months from the fixed-duration component mirrors PostgreSQL's internal representation: INTERVAL '1 month' cannot be expressed as a fixed number of microseconds, so it must be handled via calendar arithmetic.
func ParseIntervalString ¶ added in v0.11.0
ParseIntervalString parses an interval specification string such as "3 days", "1 year 2 months", "-4 hours 30 minutes".
Supported units (case-insensitive, singular or plural):
year, month, week, day, hour, minute, second, microsecond
Weeks are converted to days (1 week = 7 days) and stored in Micros. Negative values are supported per-component: "-1 day 2 hours".
type Iterator ¶
type Iterator struct {
// contains filtered or unexported fields
}
Iterator ...
func NewIterator ¶
NewIterator ...
func NewSliceIterator ¶ added in v0.17.0
NewSliceIterator returns an Iterator that yields rows from rows in order.
type Join ¶
type Join struct {
TableName string
TableAlias string
Conditions Conditions
Joins []Join
Type JoinType
}
Join ...
type JoinAlgorithm ¶ added in v0.47.0
type JoinAlgorithm int
JoinAlgorithm selects the execution strategy for a single join.
const ( // JoinAlgorithmNestedLoop uses the existing nested-loop strategy: either an // index point-lookup on the inner table (when an index exists) or a full // sequential scan of the inner table for every outer row. JoinAlgorithmNestedLoop JoinAlgorithm = iota // JoinAlgorithmHash builds an in-memory hash table from the inner (build) // side once, then probes it for every outer row. O(N+M) instead of O(N×M). // Only chosen when no index exists on the inner join column. JoinAlgorithmHash )
type JoinColumnPair ¶
JoinColumnPair represents a pair of columns used in a JOIN ON condition
type JoinPlan ¶
type JoinPlan struct {
OuterJoinColumn string
InnerJoinColumn string
Conditions Conditions
JoinColumnPairs []JoinColumnPair
Type JoinType
LeftScanIndex int
RightScanIndex int
Algorithm JoinAlgorithm
}
JoinPlan represents a join operation between two scans
type LRUCache ¶
type LRUCache[T any] interface { Get(T) (any, bool) GetAndPromote(T) (any, bool) Put(T, any, bool) EvictIfNeeded() (T, bool) }
LRUCache ...
type LeafNode ¶
type LeafNode struct {
Cells []Cell
Header LeafNodeHeader
}
LeafNode ...
func (*LeafNode) Clone ¶
Clone cretes a shallow copy of the leaf node, sharing value slices until they are about to be modified at which point PrepareModifyCell should be called to clone the value slice for that cell.
func (*LeafNode) HasSpaceForRow ¶
HasSpaceForRow ...
func (*LeafNode) PrepareModifyCell ¶
PrepareModifyCell ensures the cell at idx is copy-on-write safe before modification.
type LeafNodeHeader ¶
LeafNodeHeader ...
type LogicOp ¶
type LogicOp int
LogicOp represents a boolean logic operator (AND or OR) used in a ConditionNode.
type OneOrMore ¶
type OneOrMore []Conditions
OneOrMore contains a slice of multiple groups of singular condition, each group joined by OR boolean operator. Every singular condition in each group is joined by AND with other conditions in the same slice.
func NewOneOrMore ¶
func NewOneOrMore(conditionGroups ...Conditions) OneOrMore
NewOneOrMore creates a new OneOrMore from the given condition groups.
func (OneOrMore) LastCondition ¶
LastCondition returns the last condition in the last group, if any.
func (OneOrMore) UpdateLast ¶
UpdateLast replaces the last condition in the last group.
type Operand ¶
type Operand struct {
Value any
Type OperandType
}
Operand holds a typed value on one side of a condition expression.
type OperandType ¶
type OperandType int
OperandType classifies the value on either side of a condition operator.
const ( // OperandField means the operand is a table column name. OperandField OperandType = iota + 1 OperandPlaceholder OperandNull OperandQuotedString OperandBoolean OperandInteger OperandFloat OperandList // OperandSubquery holds a *Statement SELECT that is evaluated before the // outer scan begins and replaced with a concrete scalar or list value. OperandSubquery )
OperandType constants define the kinds of operand values.
type Operator ¶
type Operator int
Operator represents a SQL comparison operator used in WHERE conditions.
const ( // Eq -> "=" Eq Operator = iota + 1 // Ne -> "!=" Ne // Gt -> ">" Gt // Lt -> "<" Lt // Gte -> ">=" Gte // Lte -> "<=" Lte // In -> "IN (...)" In // NotIn -> "NOT IN (...)" NotIn // Like -> "LIKE" Like // NotLike -> "NOT LIKE" NotLike // Between -> "BETWEEN ... AND ..." Between // NotBetween -> "NOT BETWEEN ... AND ..." NotBetween )
type OverflowPage ¶
type OverflowPage struct {
Data []byte
Header OverflowPageHeader
}
OverflowPage ...
type OverflowPageHeader ¶
type OverflowPageHeader struct {
NextPage PageIndex // 0 if last page
DataSize uint32 // Actual data size in this page
}
OverflowPageHeader ...
type Page ¶
type Page struct {
IndexNode any
OverflowPage *OverflowPage
FreePage *FreePage
InternalNode *InternalNode
LeafNode *LeafNode
IndexOverflowNode *IndexOverflowPage
Index PageIndex
}
Page ...
type PageSaver ¶
type PageSaver interface {
SavePage(context.Context, PageIndex, *Page)
SaveHeader(context.Context, DatabaseHeader)
SetWALIndex(*WALIndex)
Flusher
}
PageSaver ...
type PageUnmarshaler ¶
PageUnmarshaler ...
type Pager ¶
type Pager interface {
GetPage(context.Context, PageIndex) (*Page, error)
GetHeader(context.Context) DatabaseHeader
TotalPages() uint32
}
Pager ...
type PagerFactory ¶
type PagerFactory interface {
ForTable([]Column) Pager
ForIndex(columns []Column, unique bool) Pager
}
PagerFactory ...
type PrimaryKey ¶
type PrimaryKey struct {
Index BTreeIndex
IndexInfo
Autoincrement bool
}
PrimaryKey ...
func NewPrimaryKey ¶
func NewPrimaryKey(indexName string, columns []Column, autoincrement bool) PrimaryKey
NewPrimaryKey ...
type QueryPlan ¶
type QueryPlan struct {
Scans []Scan
Joins []JoinPlan // JOIN operations to perform
// Ordering
OrderBy []OrderBy
SortInMemory bool
SortReverse bool
}
QueryPlan determines how to execute a query
func (QueryPlan) Execute ¶
func (p QueryPlan) Execute(ctx context.Context, provider TableProvider, selectedFields []Field, out func(Row) error) error
Execute runs the query plan, calling out for every row produced. out receives each row synchronously on the caller's goroutine; no internal goroutines or channels are created. JOIN queries are the exception: they still drive executeNestedLoopJoin in a helper goroutine internally so that the nested-loop logic can use a channel, but the rows are forwarded to out before Execute returns.
type RangeBound ¶
RangeBound ...
type RangeCondition ¶
type RangeCondition struct {
Lower *RangeBound // nil = unbounded
Upper *RangeBound // nil = unbounded
}
RangeCondition ...
type Row ¶
type Row struct {
Columns []Column
Values []OptionalValue
Key RowID
}
Row ...
func NewRowWithValues ¶
func NewRowWithValues(columns []Column, values []OptionalValue) Row
NewRowWithValues ...
func (Row) CheckConditions ¶
func (r Row) CheckConditions(condGroup Conditions) (bool, error)
CheckConditions ...
func (Row) CheckOneOrMore ¶
CheckOneOrMore checks whether row satisfies one or more sets of conditions (cond1 AND cond2) OR (cond3 and cond4) ... etc
func (Row) CheckOneOrMoreWithColumnIndexes ¶ added in v0.23.0
func (r Row) CheckOneOrMoreWithColumnIndexes(conditions OneOrMore, columnIndexes map[string]int) (bool, error)
CheckOneOrMoreWithColumnIndexes is like CheckOneOrMore but uses pre-resolved column indexes for field lookups to avoid repeated linear scans by name.
func (Row) GetColumn ¶
GetColumn returns the column and its index for the given name via linear scan.
func (Row) GetValue ¶
func (r Row) GetValue(name string) (OptionalValue, bool)
GetValue returns the value for the given column name via linear scan.
func (Row) GetValuesForColumns ¶
func (r Row) GetValuesForColumns(columns []Column) ([]OptionalValue, bool)
GetValuesForColumns ...
func (Row) NullBitmask ¶
NullBitmask returns a bitmask representing which columns are NULL
func (Row) OnlyFields ¶
OnlyFields returns a new Row containing only the specified fields. The result is accessed positionally (Values[i]) by all downstream consumers (Rows.Next, rowDistinctKey, selectGroupBy, deduplicateRows). Name-based lookups via GetColumn/GetValue fall back to a linear scan if needed.
func (Row) SetValue ¶
func (r Row) SetValue(name string, value OptionalValue) (Row, bool)
SetValue returns true if value has changed
func (Row) Unmarshal ¶
Unmarshal decodes cell into a Row. For columns not in selectedFields, an empty OptionalValue is inserted to maintain index alignment.
func (Row) UnmarshalWithMask ¶ added in v0.23.0
UnmarshalWithMask decodes cell into a Row using a precomputed column-selection mask. selectedMask must have len == len(r.Columns). A nil/empty mask means "no fields selected" (keys only; values remain zero-value placeholders).
type Scan ¶
type Scan struct {
RangeCondition RangeCondition
TableName string
TableAlias string
IndexName string
IndexColumns []Column
IndexKeys []any
Filters OneOrMore
// SubScans holds the child index scans for ScanTypeIndexIntersect.
// Each child is executed to collect RowIDs; surviving rows are fetched after intersection.
SubScans []Scan
Type ScanType
CoveringIndex bool
}
Scan ...
type ScanType ¶
type ScanType int
ScanType ...
const ( // ScanTypeSequential is a full table scan. ScanTypeSequential ScanType = iota + 1 // ScanTypeIndexAll is a full index scan. ScanTypeIndexAll // ScanTypeIndexPoint is an index lookup for specific key(s). ScanTypeIndexPoint // ScanTypeIndexRange is an index range scan. ScanTypeIndexRange // ScanTypeIndexFirst seeks to the first (smallest) key in the index — used for MIN optimisation. ScanTypeIndexFirst // ScanTypeIndexLast seeks to the last (largest) key in the index — used for MAX optimisation. ScanTypeIndexLast // ScanTypeIndexIntersect runs each sub-scan to collect RowID sets, intersects them in // memory, then fetches only the surviving rows. Used for AND conditions where two or // more independent indexes are available. ScanTypeIndexIntersect )
ScanType constants define the available index and table scan strategies.
type Schema ¶
type Schema struct {
Name string
TableName string
DDL string
Type SchemaType
RootPage PageIndex
}
Schema represents a single row in the internal schema metadata table.
type SchemaType ¶
type SchemaType int
SchemaType identifies the kind of object recorded in the schema table.
const ( // SchemaTable identifies a user table entry in the schema. SchemaTable SchemaType = iota + 1 SchemaPrimaryKey SchemaUniqueIndex SchemaSecondaryIndex // SchemaForeignKey identifies a foreign key constraint stored as a separate // schema row (Name = FK name, TableName = child table, DDL = serialised FK). SchemaForeignKey )
SchemaType constants identify the kind of object recorded in the schema table.
type Statement ¶
type Statement struct {
PrimaryKey PrimaryKey
Aliases map[string]string
Functions map[string]Function
Updates map[string]OptionalValue
Offset OptionalValue
Limit OptionalValue
TableName string
TableAlias string
IndexName string
Target string
PragmaName string
PragmaValue string
Fields []Field
Inserts [][]OptionalValue
Aggregates []AggregateExpr
GroupBy []Field
Having OneOrMore
Unions []UnionClause
Joins []Join
OrderBy []OrderBy
UniqueIndexes []UniqueIndex
ForeignKeys []ForeignKey
Columns []Column
Conditions OneOrMore
ReturningFields []Field
ExplainStatement *Statement
FromSubquery *Statement // non-nil when FROM clause is a derived table
FromSubqueryAlias string // alias for the derived table (e.g. "t" in FROM (...) t)
CTEs []CTE // non-nil for WITH … SELECT statements
Kind StatementKind
ConflictAction ConflictAction
IfNotExists bool
ExplainAnalyze bool
Distinct bool
}
Statement ...
func (Statement) AddJoin ¶
func (s Statement) AddJoin(joinType JoinType, fromTableAlias, toTable, toTableAlias string, conditions Conditions) (Statement, error)
AddJoin ...
func (Statement) BindArguments ¶
BindArguments ...
func (Statement) ColumnByName ¶
ColumnByName ...
func (Statement) InsertValuesForColumns ¶
func (s Statement) InsertValuesForColumns(insertIdx int, columns ...Column) []OptionalValue
InsertValuesForColumns ...
func (Statement) IsSelectAggregate ¶
IsSelectAggregate returns true when the SELECT list contains at least one aggregate function (SUM, AVG, MIN, MAX). COUNT(*) alone uses the legacy IsSelectCountAll path and does NOT set this flag.
func (Statement) IsSelectGroupBy ¶
IsSelectGroupBy returns true when the SELECT has a GROUP BY clause.
func (Statement) NumPlaceholders ¶
NumPlaceholders returns the number of placeholder parameters (?) in the statement.
type StatementKind ¶
type StatementKind int
StatementKind ...
const ( // CreateTable ... CreateTable StatementKind = iota + 1 DropTable CreateIndex DropIndex Insert Select Update Delete BeginTransaction CommitTransaction RollbackTransaction Analyze Vacuum Pragma Explain )
StatementKind constants enumerate the supported SQL statement types.
func (StatementKind) String ¶
func (s StatementKind) String() string
type StatementResult ¶
StatementResult ...
type SynchronousMode ¶ added in v0.32.0
type SynchronousMode int32
SynchronousMode controls when the WAL file is fsynced to disk.
The values mirror SQLite's PRAGMA synchronous settings for WAL mode:
- SynchronousOff (0): no fsyncs at all — maximum performance, no durability guarantee.
- SynchronousNormal (1): fsync only at checkpoint, not on every commit — SQLite WAL default.
- SynchronousFull (2): fsync on every WAL commit — maximum durability.
const ( // SynchronousOff skips all fsyncs. Fastest, but data loss is possible on crash. SynchronousOff SynchronousMode = 0 // SynchronousNormal fsyncs only at checkpoint (SQLite WAL default). SynchronousNormal SynchronousMode = 1 // SynchronousFull fsyncs after every WAL commit for maximum durability. SynchronousFull SynchronousMode = 2 )
type Table ¶
type Table struct {
PrimaryKey PrimaryKey
UniqueIndexes map[string]UniqueIndex
SecondaryIndexes map[string]SecondaryIndex
// ForeignKeys holds all outgoing FK constraints defined on this table.
ForeignKeys []ForeignKey
Name string
Columns []Column
// contains filtered or unexported fields
}
Table ...
func NewTable ¶
func NewTable(logger *zap.Logger, pager TxPager, txManager *TransactionManager, name string, columns []Column, rootPageIdx PageIndex, provider TableProvider, opts ...TableOption) *Table
NewTable ...
func (*Table) ColumnByName ¶
ColumnByName ...
func (*Table) DeleteKey ¶
DeleteKey deletes a key from the table, when this is called, you should already have located the leaf that contains the key and pass its page and cell index here. The deletion process starts at the leaf and then recursively bubbles up the tree.
func (*Table) HasIndexOnColumn ¶
HasIndexOnColumn ...
func (*Table) HasIndexOnColumns ¶
HasIndexOnColumns ...
func (*Table) IndexByName ¶
func (t *Table) IndexByName(name string) (BTreeIndex, bool)
IndexByName ...
func (*Table) IndexColumnsByIndexName ¶
IndexColumnsByIndexName ...
func (*Table) IndexInfoByColumnName ¶
IndexInfoByColumnName ...
func (*Table) IndexInfoByColumns ¶
IndexInfoByColumns looks up an index whose columns (in order) exactly match the given slice.
func (*Table) InternalNodeInsert ¶
func (t *Table) InternalNodeInsert(ctx context.Context, parentPageIdx, childPageIdx PageIndex) error
InternalNodeInsert adds a new child/key pair to the parent internal node corresponding to the given child page.
func (*Table) InternalNodeSplitInsert ¶
InternalNodeSplitInsert splits an internal node and inserts the child. It creates a sibling to hold (n-1)/2 keys, updates the parent's max key, inserts the sibling into the parent (possibly triggering further splits), and creates a new root if the original node was the root.
func (*Table) PlanQuery ¶
PlanQuery creates a query plan based on the statement and table schema. This is in no way a sophisticated query planner, but a simple heuristic-based approach to determine whether an index scan can be used based on the WHERE conditions.
Consider a table with the following schema: CREATE TABLE users (
id INTEGER PRIMARY KEY, email TEXT UNIQUE, non_indexed_col TEXT, created TIMESTAMP DEFAULT NOW()
); CREATE INDEX "idx_created" ON "users" (created);
If we select without a WHERE clause, we default to a sequential scan: SELECT * from users;
If a WHERE clause cannot be fully satisfied by an index or combination of indexes, we fall back to a sequential scan.
Remember that if you have multiple conditions separated by OR, if a single one does not use an index, we have to do a sequential scan anyway. Also remember that non equality conditions using != or NOT IN or conditions comparing to NULL cannot use indexes.
SEQUENTIAL SCANS: ----------------- SELECT * from users WHERE non_indexed_col = 'baz'; SELECT * from users WHERE id = 1 OR non_indexed_col = 'baz'; SELECT * FROM users WHERE id = 1 OR id IS NULL; SELECT * FROM users WHERE pk NOT IN (1,2,3);
INDEX POINT SCANS: ------------------ When there are only equality conditions on indexed columns (primary key or unique indexes), we can do index point scans:
SELECT * from users WHERE id = 1; - single point scan on PK index SELECT * from users WHERE id IN (1, 2, 3); - single point scan on PK index SELECT * from users WHERE email = 'foo@example.com'; - single point scan on unique index SELECT * FROM users WHERE id = 1 OR id id = 2 OR email = 'foo@example.com'; - multiple point scans
RANGE SCANS: ------------ For >, >=, <, <= conditions on indexed columns, we can do range scans:
SELECT * FROM users WHERE id > 10 AND id < 20 AND non_indexed_col = 'baz'; - range scan on PK index
For OR conditions, we can do multiple range scans if each condition group has a range condition. For example, following query can be executed as two range scans, one on PK column and one on secondary index:
SELECT * FROM users WHERE (id >= 10 AND id <= 20) OR created >= '2024-01-01';
When combining range scans with ordering, we currently fall back to in-memory sort:
SELECT * FROM users WHERE id >= 10 AND id <= 20 ORDER BY created DESC;
ORDER BY: --------- SELECT * from users ORDER BY id DESC; - use PK index for ordering SELECT * from users ORDER BY created DESC; - use index on created for ordering SELECT * from users ORDER BY non_indexed_col; - order in memory
func (*Table) RemoveSecondaryIndex ¶
RemoveSecondaryIndex ...
func (*Table) Seek ¶
Seek the cursor for a key, if it does not exist then return the cursor for the page and cell where it should be inserted
func (*Table) SeekNextRowID ¶
SeekNextRowID returns cursor pointing at the position after the last row ID plus a new row ID to insert
func (*Table) SetSecondaryIndex ¶
func (t *Table) SetSecondaryIndex(name string, columns []Column, index BTreeIndex)
SetSecondaryIndex ...
type TableOption ¶
type TableOption func(*Table)
TableOption ...
func WithChildFKChecker ¶ added in v0.52.0
func WithChildFKChecker(fn func(context.Context, Row) error) TableOption
WithChildFKChecker wires up a callback that checks outgoing FK constraints. Called by *Database; must only be invoked while d.dbLock is held (write).
func WithForeignKeys ¶ added in v0.52.0
func WithForeignKeys(fks []ForeignKey) TableOption
WithForeignKeys sets the outgoing FK constraints on the table.
func WithParallelScan ¶ added in v0.51.0
func WithParallelScan(enabled bool) TableOption
WithParallelScan enables or disables concurrent leaf-page scanning for this table.
func WithParentFKChecker ¶ added in v0.52.0
func WithParentFKChecker(fn func(context.Context, Row) error) TableOption
WithParentFKChecker wires up a callback that enforces inbound FK constraints on DELETE. Called by *Database; must only be invoked while d.dbLock is held (write).
func WithParentFKUpdateEnforcer ¶ added in v0.53.0
WithParentFKUpdateEnforcer wires up a callback that enforces inbound FK constraints on UPDATE. Called by *Database; must only be invoked while d.dbLock is held (write).
func WithReferencedColumns ¶ added in v0.52.0
func WithReferencedColumns(cols map[string]bool) TableOption
WithReferencedColumns marks which columns of this table are FK targets in other tables.
func WithRowCountGetter ¶ added in v0.29.0
func WithRowCountGetter(fn func() int64) TableOption
WithRowCountGetter sets an O(1) row-count accessor on the table. When set, COUNT(*) with no WHERE clause returns the value directly instead of performing a leaf-page walk.
func WithSecondaryIndex ¶
func WithSecondaryIndex(index SecondaryIndex) TableOption
WithSecondaryIndex ...
type TableProvider ¶
TableProvider provides thread-safe access to tables
type TextPointer ¶
TextPointer is stored in the main row; text of length <= MaxInlineVarchar is stored inline, otherwise it points to an overflow page.
func (*TextPointer) Marshal ¶
func (tp *TextPointer) Marshal(buf []byte, i uint64) error
Marshal ...
func (TextPointer) String ¶
func (tp TextPointer) String() string
type Time ¶
type Time struct {
Year int32 // astonomical year numbering, e.g. 1 BC = year 0, 2 BC = -1, etc.
Month int8
Day int8
Hour int8
Minutes int8
Seconds int8
Microseconds int32
}
Time is a custom type implementing a PostgreSQL-like TIMESTAMP type without timezone. low value 4713 BC high value 294276 AD
func FromMicroseconds ¶
FromMicroseconds constructs a Time from microseconds since 2000-01-01 00:00:00 UTC.
func MustParseTimestamp ¶
MustParseTimestamp parses a timestamp string and panics on error.
func ParseTimestamp ¶
ParseTimestamp parses a PostgreSQL-style timestamp string into a Time value.
func (Time) AddInterval ¶ added in v0.11.0
AddInterval adds (sign=+1) or subtracts (sign=-1) iv from t.
Month arithmetic is calendar-aware: adding 1 month to Jan 31 yields the last day of February (28 or 29 depending on the year). The day component of the interval uses fixed 86 400-second days, consistent with PostgreSQL.
func (Time) TotalMicroseconds ¶
TotalMicroseconds returns the microsecond count since 2000-01-01 00:00:00 UTC. Negative values represent dates before 2000-01-01 00:00:00 UTC.
type TimestampMicros ¶ added in v0.39.0
type TimestampMicros int64
TimestampMicros is the in-memory representation of a TIMESTAMP column value. It stores microseconds since 2000-01-01 00:00:00 UTC as a named int64 so that it is distinguishable from numeric int64 values in type switches, while still fitting inline in an any interface word — no heap allocation.
func MustParseTimestampMicros ¶ added in v0.39.0
func MustParseTimestampMicros(timestampStr string) TimestampMicros
MustParseTimestampMicros parses a timestamp string into a TimestampMicros and panics on error.
type Transaction ¶
type Transaction struct {
DDLChanges DDLChanges
StartTime time.Time
ReadSet map[PageIndex]uint64
WriteSet map[PageIndex]WriteInfo
DBHeaderRead *uint64
DBHeaderWrite *DatabaseHeader
ID TransactionID
Status TransactionStatus
SnapshotSeq uint64
ReadOnly bool
// contains filtered or unexported fields
}
Transaction tracks the read and write sets for optimistic concurrency control.
func MustTxFromContext ¶
func MustTxFromContext(ctx context.Context) *Transaction
MustTxFromContext retrieves the current transaction from the context and panics if none is present.
func TxFromContext ¶
func TxFromContext(ctx context.Context) *Transaction
TxFromContext retrieves the current transaction from the context, or nil if none.
func (*Transaction) Abort ¶
func (tx *Transaction) Abort()
Abort sets status to TxAborted and discards all in-memory changes.
func (*Transaction) AddRowCountDelta ¶ added in v0.29.0
func (tx *Transaction) AddRowCountDelta(table string, delta int64)
AddRowCountDelta records a net row-count change for the named table. It is a no-op for read-only transactions.
func (*Transaction) Commit ¶
func (tx *Transaction) Commit()
Commit marks the transaction as committed.
func (*Transaction) GetDBHeaderReadVersion ¶
func (tx *Transaction) GetDBHeaderReadVersion() (uint64, bool)
GetDBHeaderReadVersion returns the version of the database header as it was read, if any.
func (*Transaction) GetModifiedDBHeader ¶
func (tx *Transaction) GetModifiedDBHeader() (*DatabaseHeader, bool)
GetModifiedDBHeader returns the in-memory modified database header, if any.
func (*Transaction) GetModifiedPage ¶
func (tx *Transaction) GetModifiedPage(pageIdx PageIndex) (*Page, bool)
GetModifiedPage returns the in-memory modified copy of the page at pageIdx, if any.
func (*Transaction) GetReadVersion ¶ added in v0.26.0
func (tx *Transaction) GetReadVersion(pageIdx PageIndex) (uint64, bool)
GetReadVersion returns the version recorded when the given page was read, if any.
func (*Transaction) GetReadVersions ¶
func (tx *Transaction) GetReadVersions() map[PageIndex]uint64
GetReadVersions returns a copy of the page read-version map.
func (*Transaction) GetWriteVersions ¶
func (tx *Transaction) GetWriteVersions() map[PageIndex]WriteInfo
GetWriteVersions returns the transaction's write set.
func (*Transaction) RowCountDeltas ¶ added in v0.29.0
func (tx *Transaction) RowCountDeltas() map[string]int64
RowCountDeltas returns the accumulated row-count deltas. The returned map must not be modified by the caller.
func (*Transaction) TrackDBHeaderRead ¶
func (tx *Transaction) TrackDBHeaderRead(version uint64)
TrackDBHeaderRead records the version of the database header when it was read. It is a no-op for read-only transactions.
func (*Transaction) TrackDBHeaderWrite ¶
func (tx *Transaction) TrackDBHeaderWrite(header DatabaseHeader)
TrackDBHeaderWrite records a modified database header in the transaction write set.
func (*Transaction) TrackRead ¶
func (tx *Transaction) TrackRead(pageIdx PageIndex, version uint64)
TrackRead records that the given page was read at the given version. It is a no-op for read-only transactions.
func (*Transaction) TrackWrite ¶
func (tx *Transaction) TrackWrite(pageIdx PageIndex, page, originalPage *Page, table, index string)
TrackWrite records a modified page in the transaction write set. originalPage is the page as it was before modification; it is stored for MVCC snapshot reads and must not be nil for pages that existed prior to this transaction (use nil for newly-allocated pages).
type TransactionID ¶
type TransactionID uint64
TransactionID is the unique identifier for a transaction.
type TransactionManager ¶
type TransactionManager struct {
// contains filtered or unexported fields
}
TransactionManager coordinates optimistic concurrency control for the database.
func NewTransactionManager ¶
func NewTransactionManager(logger *zap.Logger, dbFilePath string, factory TxPagerFactory, saver PageSaver, ddlSaver DDLSaver) *TransactionManager
NewTransactionManager creates and returns a new TransactionManager.
func (*TransactionManager) BeginReadOnlyTransaction ¶ added in v0.17.0
func (tm *TransactionManager) BeginReadOnlyTransaction(ctx context.Context) *Transaction
BeginReadOnlyTransaction starts a read-only transaction with snapshot isolation. The transaction sees a consistent snapshot of the database as of the moment it begins: any write committed after this call is invisible to it. TrackRead calls are no-ops; conflict validation is skipped at commit time. Read-only transactions never return ErrTxConflict.
SnapshotSeq is captured inside tm.mu so it is atomic with the transaction registration — preventing a race where a write commits between the map insert and the seq capture.
func (*TransactionManager) BeginTransaction ¶
func (tm *TransactionManager) BeginTransaction(ctx context.Context) *Transaction
BeginTransaction starts a new transaction and registers it with the manager.
func (*TransactionManager) CheckpointWAL ¶ added in v0.12.0
func (tm *TransactionManager) CheckpointWAL(dbFile DBFile) error
CheckpointWAL checkpoints the WAL into dbFile, then truncates it.
Checkpoint sequence (all under walWriteMu so no concurrent writers can interleave):
- Write every unique page in the WAL to its correct offset in dbFile.
- fsync dbFile.
- Truncate the WAL file and write fresh salts (invalidates stale frames).
- Reset the in-memory WAL index (under tm.mu).
Returns ErrNotWALMode if no WAL is configured. Returns ErrCheckpointBlockedByReaders if any read-only snapshot transaction is currently active. Callers should retry after the readers have finished.
func (*TransactionManager) CommitTransaction ¶
func (tm *TransactionManager) CommitTransaction(ctx context.Context, tx *Transaction) error
CommitTransaction validates the write set for conflicts and, if clean, persists all changes. When a WAL is configured it uses the WAL commit path; otherwise it writes directly to the pager (used by unit tests that do not set up a WAL file).
func (*TransactionManager) ExecuteInTransaction ¶
func (tm *TransactionManager) ExecuteInTransaction(ctx context.Context, fn func(ctx context.Context) error) error
ExecuteInTransaction runs fn within a transaction, committing on success or rolling back on failure.
func (*TransactionManager) ExecuteReadOnlyTransaction ¶ added in v0.17.0
func (tm *TransactionManager) ExecuteReadOnlyTransaction(ctx context.Context, fn func(ctx context.Context) error) error
ExecuteReadOnlyTransaction runs fn within a read-only transaction. Read tracking is disabled so no ReadSet is built and conflict validation is skipped at commit time. fn must not perform any writes.
func (*TransactionManager) GlobalDBHeaderVersion ¶
func (tm *TransactionManager) GlobalDBHeaderVersion(ctx context.Context) uint64
GlobalDBHeaderVersion returns the current committed version of the database header.
func (*TransactionManager) GlobalPageVersion ¶
func (tm *TransactionManager) GlobalPageVersion(ctx context.Context, pageIdx PageIndex) uint64
GlobalPageVersion returns the current committed version of the given page.
func (*TransactionManager) PageLastCommittedSeq ¶ added in v0.26.0
func (tm *TransactionManager) PageLastCommittedSeq(pageIdx PageIndex) uint64
PageLastCommittedSeq returns the commitSeq at which pageIdx was last updated in the shared page cache. Used by ReadPage to decide whether the cached version is safe to serve to a snapshot reader.
func (*TransactionManager) PageVersionAtSnapshot ¶ added in v0.26.0
func (tm *TransactionManager) PageVersionAtSnapshot(pageIdx PageIndex, snapshotSeq uint64) (*Page, bool)
PageVersionAtSnapshot returns the *Page that was current for the given snapshotSeq by binary-searching the version history. ok is false when no suitable entry exists (page either predates any WAL write or was newly allocated after the snapshot).
func (*TransactionManager) RollbackTransaction ¶
func (tm *TransactionManager) RollbackTransaction(ctx context.Context, tx *Transaction)
RollbackTransaction aborts the transaction and discards all in-memory changes.
func (*TransactionManager) SetCheckpointFunc ¶ added in v0.12.0
func (tm *TransactionManager) SetCheckpointFunc(fn func() error)
SetCheckpointFunc registers a callback that is invoked by runAutoCheckpoint when the WAL frame count exceeds checkpointThreshold. Typically set to Database.Checkpoint so the auto-checkpoint path mirrors the manual one.
func (*TransactionManager) SetRowCountApplier ¶ added in v0.29.0
func (tm *TransactionManager) SetRowCountApplier(fn func(map[string]int64))
SetRowCountApplier registers a callback that is invoked after each successful write commit with the net row-count deltas for the transaction. The Database uses this to keep in-memory row counts up to date so that COUNT(*) queries can be answered in O(1) without a leaf-page walk.
type TransactionStatus ¶
type TransactionStatus int
TransactionStatus represents the lifecycle state of a transaction.
const ( // TxActive means the transaction is in progress and has not yet been committed or aborted. TxActive TransactionStatus = iota + 1 // TxCommitted means the transaction has been successfully committed. TxCommitted // TxAborted means the transaction has been rolled back or aborted. TxAborted )
TransactionStatus constants describe the lifecycle state of a transaction.
type TransactionalPager ¶
type TransactionalPager struct {
Pager
// contains filtered or unexported fields
}
TransactionalPager wraps a base Pager and routes reads and writes through the current transaction.
func NewTransactionalPager ¶
func NewTransactionalPager(basePager Pager, txManager *TransactionManager, table, index string) *TransactionalPager
NewTransactionalPager creates a TransactionalPager for the given table and index names.
func (*TransactionalPager) AddFreePage ¶
func (tp *TransactionalPager) AddFreePage(ctx context.Context, pageIdx PageIndex) error
AddFreePage marks pageIdx as a free page and prepends it to the free list.
func (*TransactionalPager) GetFreePage ¶
func (tp *TransactionalPager) GetFreePage(ctx context.Context) (*Page, error)
GetFreePage returns a free page from the free list, or allocates a new one.
func (*TransactionalPager) GetOverflowPage ¶
func (tp *TransactionalPager) GetOverflowPage(ctx context.Context, pageIdx PageIndex) (*Page, error)
GetOverflowPage returns a writable copy of the overflow page at pageIdx.
func (*TransactionalPager) ModifyPage ¶
ModifyPage returns a writable copy of the page at pageIdx, creating one if it doesn't exist in the write set.
func (*TransactionalPager) ReadPage ¶
ReadPage returns the page at pageIdx, returning the in-progress write copy if it exists.
For read-only (snapshot) transactions the method enforces snapshot isolation:
- If the page was last committed at or before tx.SnapshotSeq, the shared page cache is safe to use — no concurrent write has touched it since the snapshot started.
- Otherwise the method retrieves the historical version from the TransactionManager's page-version history (saved at commit time by the writer that superseded the page).
- If no historical version is found (the page was newly allocated after the snapshot), the cached version is returned as a safe fallback; this should not occur during normal B+ tree traversal because pre-snapshot pointer chains never reference post-snapshot pages.
type TxPager ¶
type TxPager interface {
ReadPage(context.Context, PageIndex) (*Page, error)
ModifyPage(context.Context, PageIndex) (*Page, error)
GetFreePage(context.Context) (*Page, error)
AddFreePage(context.Context, PageIndex) error
GetOverflowPage(context.Context, PageIndex) (*Page, error)
}
TxPager ...
type TxPagerFactory ¶
TxPagerFactory ...
type UnionClause ¶ added in v0.9.0
UnionClause represents a UNION or UNION ALL branch appended to a SELECT statement.
type WAL ¶ added in v0.12.0
type WAL struct {
// contains filtered or unexported fields
}
WAL is a write-ahead log providing crash-safe durability for the database.
On each commit the transaction manager serialises all modified pages as WAL frames and calls AppendTransaction. A final "commit frame" (CommitSize > 0) marks the transaction as durable. Readers check the WAL index (see WALIndex) before reading the main DB file so they always see the latest committed version of any page.
Periodically, or on clean open, committed frames are copied back to the main DB file via Checkpoint and the WAL is truncated.
Write buffering: when flushThreshold > 0 frames from multiple transactions are accumulated in pendingBuf and written to the file in a single WriteAt once pendingLen >= flushThreshold. This reduces syscall overhead for high-frequency single-row-per-transaction workloads. flushThreshold == 0 (the default) flushes after every AppendTransaction, preserving the previous behaviour. SynchronousFull always flushes immediately regardless of the threshold.
func CreateWAL ¶ added in v0.12.0
CreateWAL creates a new WAL file (truncating any existing file at that path).
func OpenWAL ¶ added in v0.12.0
OpenWAL opens an existing WAL file for reading and appending. Returns (nil, nil) when the WAL file does not exist (clean state).
func OpenWALAndRebuildIndex ¶ added in v0.12.0
func OpenWALAndRebuildIndex(dbPath string, pageSize uint32, walIndex *WALIndex) (wal *WAL, recovered bool, err error)
OpenWALAndRebuildIndex is the startup routine for WAL mode.
It checks for an existing WAL file at dbPath+"-wal":
If the file exists, it opens it for appending, reads all committed frames, and rebuilds walIndex from those frames. This is the crash- recovery path: committed writes that had not yet been checkpointed to the main DB file are reinstated in the in-memory index so reads see the correct data immediately.
If no WAL file exists, a fresh WAL file is created.
The caller owns the returned *WAL and must call WAL.Close() when done. walIndex is populated in-place; it must be non-nil. recovered is true when an existing WAL file with committed frames was found.
func (*WAL) AppendTransaction ¶ added in v0.12.0
AppendTransaction serialises all modified pages as WAL frames into the write buffer and, when the buffer reaches the flush threshold (or when SynchronousFull mode is active), writes it to the OS page cache in a single WriteAt call. The last frame is marked as a commit frame (CommitSize = len(pages)). pages must be non-empty; each Data slice must be exactly pageSize bytes.
func (*WAL) Checkpoint ¶ added in v0.12.0
Checkpoint copies all committed WAL pages to the database file. It writes the latest version of each page (last write wins when a page appears in multiple transactions) and then fsyncs the database file. Callers should call Truncate after a successful checkpoint.
func (*WAL) Close ¶ added in v0.12.0
Close flushes any pending frames, fsyncs (unless SynchronousOff), and closes the WAL file. On clean shutdown this guarantees all committed transactions are durable before the file handle is released.
func (*WAL) Delete ¶ added in v0.12.0
Delete closes and removes the WAL file. Used when transitioning back to a clean (no-WAL) state, e.g. after a full checkpoint on clean shutdown.
func (*WAL) Flush ¶ added in v0.34.0
Flush writes any buffered WAL frames to the OS page cache. It is a no-op when there is nothing pending. Called automatically by Checkpoint, Truncate, and Close; callers that need strict write-order guarantees can call it explicitly.
func (*WAL) FrameCount ¶ added in v0.12.0
FrameCount returns the total number of frame slots since the last Truncate, including frames that are buffered but not yet flushed to the file.
func (*WAL) ReadAllFrames ¶ added in v0.12.0
func (w *WAL) ReadAllFrames() ([]WALReadFrame, error)
ReadAllFrames scans the WAL file from the beginning and returns every frame that belongs to a committed transaction. Frames whose salts or CRCs do not match are treated as the end of the valid region; any pending (uncommitted) frames before the scan stops are silently discarded.
func (*WAL) SetSynchronous ¶ added in v0.32.0
func (w *WAL) SetSynchronous(mode SynchronousMode)
SetSynchronous changes the synchronous mode. The new value takes effect on the next WAL commit (AppendTransaction call).
func (*WAL) SetWriteBufferSize ¶ added in v0.34.0
SetWriteBufferSize sets the target size for write batching. When > 0, AppendTransaction accumulates serialised frames up to this many bytes before issuing a WriteAt to the OS. 0 (the default) disables buffering and flushes after every AppendTransaction, matching the previous behaviour. SynchronousFull always flushes immediately regardless of this setting.
func (*WAL) Synchronous ¶ added in v0.32.0
func (w *WAL) Synchronous() SynchronousMode
Synchronous returns the current synchronous mode.
type WALConfig ¶ added in v0.12.0
type WALConfig struct {
WAL *WAL
Index *WALIndex
DBFile DBFile
CheckpointThreshold int
WALWriteBufferSize int // bytes to buffer before flushing; 0 = flush every commit
Synchronous SynchronousMode
}
WALConfig bundles the Write-Ahead Log objects that NewDatabase needs. Pass nil when creating in-memory/test databases that do not require WAL.
type WALIndex ¶ added in v0.12.0
type WALIndex struct {
// contains filtered or unexported fields
}
WALIndex is an in-memory map from page index to the latest raw page bytes that have been committed to the WAL but not yet checkpointed to the main DB file. It is the authoritative source for the current page content during the window between a WAL commit and the next checkpoint.
All methods are safe for concurrent use.
Lifecycle:
- Created empty at database open via NewWALIndex.
- Populated from the WAL file via Rebuild when a non-empty WAL is found.
- Updated after each successful AppendTransaction via Update.
- Reset after a successful Checkpoint + Truncate via Reset.
The pager (Phase 4) calls Lookup before reading the DB file so readers always see the latest committed version of every page.
func NewWALIndex ¶ added in v0.12.0
func NewWALIndex() *WALIndex
NewWALIndex creates an empty WALIndex.
func (*WALIndex) Has ¶ added in v0.12.0
Has reports whether pageIdx has a committed WAL entry in the index.
func (*WALIndex) Lookup ¶ added in v0.12.0
Lookup returns the raw page bytes for pageIdx if the page has a committed WAL entry that has not yet been checkpointed. The returned slice is a direct reference into the index — callers must treat it as read-only and must not hold it across a Reset call (which replaces the map) if mutations are possible. In practice the pager unmarshals the bytes immediately and does not retain the slice, making this safe.
func (*WALIndex) MaxPageIndex ¶ added in v0.12.0
MaxPageIndex returns the largest page index stored in the WAL index, or 0 if the index is empty. Used by the pager to initialise totalPages when the DB file is empty (WAL-only mode) so that new-page allocation never clobbers existing WAL pages.
func (*WALIndex) Rebuild ¶ added in v0.12.0
func (wi *WALIndex) Rebuild(frames []WALReadFrame)
Rebuild replaces the index contents with the latest committed frame for each page found in frames. frames is expected to be the result of WAL.ReadAllFrames: all entries are already validated and belong to committed transactions. When the same page appears multiple times, the last occurrence wins (matching WAL semantics — later frames are more recent).
Rebuild takes ownership of each f.Data slice — callers must not use the slices after this call returns.
func (*WALIndex) Reset ¶ added in v0.12.0
func (wi *WALIndex) Reset()
Reset discards all entries. Called after a successful checkpoint + WAL truncation to reflect that the WAL no longer contains any data that is not already in the main DB file.
func (*WALIndex) Size ¶ added in v0.12.0
Size returns the number of unique page indices currently in the index.
func (*WALIndex) Update ¶ added in v0.12.0
Update records the latest raw page bytes for pageIdx and returns the previous buffer (if any) so the caller can recycle it. Update takes ownership of data — the caller must not read or write the slice after this call. If a prior entry exists for pageIdx it is overwritten (later write wins).
type WALPage ¶ added in v0.12.0
WALPage holds the page index and raw serialised content for one page to be appended to the WAL.
type WALReadFrame ¶ added in v0.12.0
WALReadFrame is a single validated, committed frame returned by ReadAllFrames.
Source Files
¶
- analyze.go
- check.go
- compare.go
- composite_key.go
- condition.go
- condition_node.go
- config.go
- covering_index.go
- cte.go
- cursor.go
- database.go
- database_options.go
- database_schema.go
- delete.go
- derived_table.go
- explain.go
- expr.go
- foreign_key.go
- free_page.go
- hash_join.go
- header.go
- index.go
- index_cursor.go
- index_node.go
- index_overflow.go
- index_pager.go
- index_scan.go
- insert.go
- integrity_check.go
- internal_node.go
- interval.go
- leaf_node.go
- like.go
- minisql.go
- node.go
- overflow_page.go
- page.go
- pager.go
- pager_factory.go
- parallel_scan.go
- ports.go
- pragma.go
- query_plan.go
- query_plan_join.go
- query_plan_order.go
- query_plan_stats.go
- returning.go
- row.go
- row_heap.go
- select.go
- sort.go
- stmt.go
- stmt_join.go
- stmt_result.go
- subquery.go
- sync_file.go
- table.go
- table_pager.go
- table_primary_key.go
- table_secondary_index.go
- table_unique_index.go
- text_pointer.go
- timestamp.go
- transaction.go
- transaction_manager.go
- transaction_pager.go
- update.go
- vacuum.go
- wal.go
- wal_index.go