Documentation
¶
Overview ¶
Package plan defines the plan-layer contract every vector-index plugin implements: hidden-table schema construction, table-function builders, plus thin redirects for the ANN rewrite (which actually lives in pkg/sql/plan).
History: an earlier iteration of this package held the entire ANN rewrite body for each algorithm — ~4000 LoC across 4 plugin directories — with a 23-method PlanBuilder facade. Single-call-site abstractions like that fight the existing "plan code lives in pkg/sql/plan" mental model. Phase 6 pulled ApplyForSort + CanApply bodies back. Plugins now own:
- BuildSecondaryIndexDefs (schema.go) — hidden-table TableDefs
- TableFuncBuilder registrations (tablefunc.go) — ivf_create / hnsw_search / ...
- thin ApplyForSort + CanApply (plan.go, ~10 LoC) — one-line redirect into the matching method on *plan.QueryBuilder
Mirrors pkg/indexplugin/compile/hooks.go for the layout (Hooks + facade in one file).
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( CreateIndexDef func(ctx CompilerContext, idx *tree.Index, indexTableName, indexAlgoTableType string, indexParts []string, isUnique bool) (*plan.IndexDef, error) MakeHiddenColDefByName func(name string) *plan.ColDef // ValidateIncludeColumns checks the INCLUDE column list. supportedTypes is // the plugin's accepted INCLUDE column types (catalog.Hooks. // SupportedIncludeColumnTypes()) — an empty slice means INCLUDE columns are // not supported by the algorithm. ValidateIncludeColumns func(ctx CompilerContext, includeCols []*tree.UnresolvedName, colMap map[string]*plan.ColDef, vecColName, pkeyName string, supportedTypes []types.T) error DeepCopyColDefList func([]*plan.ColDef) []*plan.ColDef )
Schema-build / tablefunc helper bodies live in pkg/sql/plan. They're published here as function variables (init wired up at pkg/sql/plan package load). Plugin schema.go and tablefunc.go call them as planplugin.<X>.
Functions ¶
func RegisterTableFunc ¶
func RegisterTableFunc(name string, b TableFuncBuilder)
RegisterTableFunc installs a per-name table-function builder. Called from plugin init(). Panics on duplicate registration.
pkg/sql/plan/query_builder.go consults this registry in its table-function dispatch switch (default arm) so per-algorithm builders can live entirely inside the algo's plugin package.
Types ¶
type ApplyForSortOpts ¶
ApplyForSortOpts carries per-call rewrite state. Today only IVF-FLAT's auto-mode two-scan rewrite consults these maps.
type BindContext ¶
type BindContext = any
BindContext is opaque to plugins. It's a *plan.BindContext on the inside of pkg/sql/plan; the plugin only ever receives one and passes it back into PlanBuilder.AppendNode.
type CompilerContext ¶
type CompilerContext interface {
GetContext() context.Context
// ResolveVariable forwards to the session's system-variable resolver so
// plan-time plugin code (e.g. CreateIndexDef capturing build-time session
// vars like kmeans_train_percent) can read session/system variables.
// Satisfied by pkg/sql/plan.CompilerContext.
ResolveVariable(varName string, isSystemVar, isGlobalVar bool) (interface{}, error)
}
CompilerContext is re-exported so plugin schema builders can consult database / variable state during CREATE INDEX planning without importing pkg/sql/plan. The pkg/sql/plan side type-asserts at the call boundary.
type Hooks ¶
type Hooks interface {
// BuildSecondaryIndexDefs constructs the IndexDef and TableDef list
// for this algorithm's hidden tables, when invoked from a
// `CREATE INDEX ... USING <algo>` statement that parses to
// *tree.Index. Body lives in the plugin's schema.go.
//
// The fulltext plugin returns an error from this method — it
// receives its parse tree via BuildFullTextIndexDefs instead.
BuildSecondaryIndexDefs(ctx CompilerContext, idx *tree.Index,
colMap map[string]*plan.ColDef, existedIndexes []*plan.IndexDef,
pkeyName string) ([]*plan.IndexDef, []*plan.TableDef, error)
// BuildFullTextIndexDefs is the parallel builder for fulltext
// indexes, which parse to *tree.FullTextIndex (a distinct AST
// node from *tree.Index). Vector plugins return a "not a fulltext
// index" error from this method; only the fulltext plugin's
// implementation is reachable in practice.
BuildFullTextIndexDefs(ctx CompilerContext, idx *tree.FullTextIndex,
colMap map[string]*plan.ColDef, existedIndexes []*plan.IndexDef,
pkeyName string) ([]*plan.IndexDef, []*plan.TableDef, error)
// CanApply / ApplyForSort are thin redirects implemented in the
// plugin's plan.go. Body lives on *plan.QueryBuilder in
// pkg/sql/plan/apply_indices_<algo>.go.
CanApply(pb PlanBuilder, vctx *VectorSortContext, mti *MultiTableIndexRef) (bool, error)
ApplyForSort(pb PlanBuilder, vctx *VectorSortContext, mti *MultiTableIndexRef, nodeID int32, opts ApplyForSortOpts) (int32, bool, error)
}
Hooks bundles the plan-layer callbacks each plugin must implement.
type MultiTableIndexRef ¶
type MultiTableIndexRef struct {
IndexAlgo string
IndexAlgoParams string
IndexDefs map[string]*plan.IndexDef
}
MultiTableIndexRef is the plugin-facing view of plan.MultiTableIndex.
type PlanBuilder ¶
type PlanBuilder interface {
// Primitives for tablefunc.go.
GenNewBindTag() int32
AppendNode(node *plan.Node, ctx BindContext) int32
GetContext() context.Context
// Per-algo redirects for plan.go (one pair per algorithm).
ApplyIndicesForSortUsingHnsw(vctx *VectorSortContext, mti *MultiTableIndexRef, nodeID int32, opts ApplyForSortOpts) (int32, bool, error)
ApplyIndicesForSortUsingCagra(vctx *VectorSortContext, mti *MultiTableIndexRef, nodeID int32, opts ApplyForSortOpts) (int32, bool, error)
ApplyIndicesForSortUsingIvfpq(vctx *VectorSortContext, mti *MultiTableIndexRef, nodeID int32, opts ApplyForSortOpts) (int32, bool, error)
ApplyIndicesForSortUsingIvfflat(vctx *VectorSortContext, mti *MultiTableIndexRef, nodeID int32, opts ApplyForSortOpts) (int32, bool, error)
CanApplyHnsw(vctx *VectorSortContext, mti *MultiTableIndexRef) (bool, error)
CanApplyCagra(vctx *VectorSortContext, mti *MultiTableIndexRef) (bool, error)
CanApplyIvfpq(vctx *VectorSortContext, mti *MultiTableIndexRef) (bool, error)
CanApplyIvfflat(vctx *VectorSortContext, mti *MultiTableIndexRef) (bool, error)
}
PlanBuilder is the *plan.QueryBuilder facade plugins use. Two roles:
Provide the minimum primitives the per-algo tablefunc.go needs to construct FUNCTION_SCAN nodes (GenNewBindTag, AppendNode, GetContext).
Provide the per-algo redirect methods plan.go calls. Each is implemented in pkg/sql/plan/plugin_builder.go as a one-liner that converts the exported types to internal types and invokes the real body (e.g. `applyIndicesForSortUsingHnsw`).
type TableFuncBuilder ¶
type TableFuncBuilder func(pb PlanBuilder, tbl *tree.TableFunction, ctx BindContext, exprs []*plan.Expr, children []int32) (int32, error)
TableFuncBuilder is the signature a vector-index plugin's table-function builder (e.g. ivfpq_create / ivfpq_search) must satisfy. Construct and append the FUNCTION_SCAN node; return its node ID. Use the PlanBuilder facade for any bind-tag / node-assembly primitives.
func TableFunc ¶
func TableFunc(name string) (TableFuncBuilder, bool)
TableFunc returns the registered builder for name, or (nil, false) if none is registered.
type VectorSortContext ¶
type VectorSortContext struct {
ProjNode *plan.Node
SortNode *plan.Node
ScanNode *plan.Node
ChildNode *plan.Node
OrderExpr *plan.Expr
DistFnExpr *plan.Function
SortDirection plan.OrderBySpec_OrderByFlag
Limit *plan.Expr
RankOption *plan.RankOption
// ProviderNodeID and VecArgExpr are populated only when the ORDER
// BY reaches the scan through a JOIN (today only HNSW consumes them).
ProviderNodeID int32
VecArgExpr *plan.Expr
}
VectorSortContext is the captured ORDER BY context for a vector ANN rewrite. Exported counterpart of plan.vectorSortContext. The redirect methods on PlanBuilder convert this back to the internal type before invoking the body in pkg/sql/plan.