Documentation
¶
Overview ¶
Package vectorsearch generates the pgvector k-NN SQL function for one table column and mirrors its Hasura tracking entry (P7-ADOPT-07, EPIC ADOPT D7).
Purpose: apps reach similarity search through Hasura GraphQL only (ADR 0003). A STABLE SQL function that returns SETOF the source table keeps the table's select filter on every row, so no new access path, role or grant is needed. Inputs: a Spec (schema.table.column, distance, roles) and the project dir. Outputs: a migration file, an optional live tracking call and an optional on-disk metadata mirror. Constraints: identifiers pass database.SanitizeIdentifier; the generated SQL is built with text/template over validated values only; no Postgres role, grant or connection string is ever created; metadata is never replaced.
Index ¶
- Constants
- Variables
- func CheckFunctionShape(ctx context.Context, run Exec, pg PG, s Spec) error
- func DiskFingerprint(projectDir string) (string, error)
- func InspectColumn(ctx context.Context, run Exec, pg PG, s Spec) (int, error)
- func MetadataDrift(ctx context.Context, cfg *config.Config, projectDir string) ([]string, error)
- func MirrorFunction(projectDir, schema, name string, roles []string) (file string, changed bool, err error)
- func MirrorFunctionIfUnchanged(projectDir, schema, name string, roles []string, want string) (string, bool, error)
- func ParseDim(formatType string) (int, error)
- func Render(s Spec) (string, error)
- type Deps
- type Distance
- type Exec
- type Finding
- type Options
- type PG
- type Result
- type Spec
Constants ¶
const DefaultRole = "user"
DefaultRole is the Hasura role granted when --roles is not given.
Variables ¶
var ErrDiskChanged = errors.New("on-disk metadata changed after the drift check")
ErrDiskChanged means the on-disk metadata changed after the drift check proved it equal to live Hasura; nothing was written.
var ErrUnsupportedLayout = errors.New("on-disk metadata layout is not supported for mirroring")
ErrUnsupportedLayout means the on-disk metadata is not in a layout this package edits. The caller leaves disk untouched and prints a note.
Functions ¶
func CheckFunctionShape ¶
CheckFunctionShape returns E513 when the function is missing from Postgres or exists in a shape other than the one this command generates (for example one hand-written with SECURITY DEFINER, which would bypass the row filter).
func DiskFingerprint ¶ added in v1.4.14
DiskFingerprint hashes the project's on-disk metadata: every .yaml, .yml and .json file under hasura/metadata (path and bytes, in walk order, which is lexical; editor swap files and .DS_Store are not metadata), else hasura/metadata.json. It returns "" when neither exists.
func InspectColumn ¶
InspectColumn returns the dimension of the vector(n) column named by s. A non-vector column, a missing column or table, or a column without a fixed dimension is E513.
func MetadataDrift ¶
MetadataDrift lists what differs between live Hasura and the project's on-disk metadata. Empty means no drift.
func MirrorFunction ¶
func MirrorFunction(projectDir, schema, name string, roles []string) (file string, changed bool, err error)
MirrorFunction adds the function and its role permissions to the on-disk metadata of projectDir. It returns the file it wrote and whether anything changed (false when the entry already holds every role). The edit is idempotent. ErrUnsupportedLayout means nothing was written.
func MirrorFunctionIfUnchanged ¶ added in v1.4.14
func MirrorFunctionIfUnchanged(projectDir, schema, name string, roles []string, want string) (string, bool, error)
MirrorFunctionIfUnchanged is MirrorFunction that writes only while the on-disk metadata still has fingerprint want (from DiskFingerprint taken before the drift check). The files are hashed again after the edited file is read and before it is written; a different hash is ErrDiskChanged and nothing is written. A write in the instant between that re-hash and the write itself is not caught: files carry no lock.
Types ¶
type Deps ¶
type Deps struct {
// Exec and PG read the column type from the Postgres container.
Exec Exec
PG PG
// TableTracked reports on-disk tracking: present is false when the project
// has no on-disk metadata at all.
TableTracked func(projectDir, schema, table string) (present, tracked bool, err error)
// ColumnVisible returns E514 when an on-disk select permission hides the
// column (ordering by it would reveal it); nil when all roles see it.
ColumnVisible func(projectDir, schema, table, column string) error
// Drift lists the on-disk metadata keys that differ from live Hasura.
Drift func(ctx context.Context, projectDir string) ([]string, error)
// Track sends one bulk call: pg_track_function plus a permission per role.
Track func(ctx context.Context, schema, name, table, column string, roles []string) error
// Now stamps a new migration file name.
Now func() time.Time
}
Deps are the seams Run uses; the command wires the real ones.
type Exec ¶
type Exec func(ctx context.Context, container string, cmd []string) (stdout, stderr string, err error)
Exec runs a command in a running container and returns stdout and stderr; it has the signature of docker.ExecCapture so tests inject a fake.
type Finding ¶ added in v1.4.14
Finding is one tracked search function that live metadata makes unsafe. Problems are "role: reason", sorted.
func AuditLive ¶ added in v1.4.14
AuditLive parses an export_metadata document and returns the tracked functions of the default source named <table>_nearest_<column> (the name FunctionName gives) over a tracked table of the same schema whose select permissions fail the --track checks. The second value is the number of search functions examined. The match is by name only: the metadata does not carry the function's return type, and the _nearest_ name is the one the generator owns, so a hand-written function with such a name is held to the same rule. A name that matches more than one table (a table itself named x_nearest_y) is checked against each: failing closed is the safe side for an ordering oracle.
inferred is Hasura's HASURA_GRAPHQL_INFER_FUNCTION_PERMISSIONS (true by default): every role with select on the table can call the function. When it is false only the roles with an explicit function permission can, so only their select permissions are checked; an inherited role among them stands for every role of its role set (its select comes from them).
type Options ¶
type Options struct {
Spec Spec
ProjectDir string
MigrationDir string // default <ProjectDir>/migrations
Track bool
}
Options are the caller's choices.
type PG ¶
PG names the Postgres container and the role and database psql uses inside it. The role is the container's own superuser: this is the CLI's admin path (like db migrate), not a credential handed to apps.
type Result ¶
type Result struct {
Function string `json:"function"`
Table string `json:"table"`
Column string `json:"column"`
Dim int `json:"dim"`
Distance string `json:"distance"`
Roles []string `json:"roles"`
Migration string `json:"migration"`
MigrationNew bool `json:"migration_written"`
Tracked bool `json:"tracked"`
DiskMetadata string `json:"disk_metadata"` // updated | unchanged | skipped | none
Note string `json:"note"`
}
Result is what Run did; it is also the --json envelope data.
type Spec ¶
type Spec struct {
Schema string
Table string
Column string
Dim int // read from the column type by Inspect
Distance Distance // "" means cosine
Roles []string // empty means [DefaultRole]
}
Spec describes one generated function.
func ParseTarget ¶
ParseTarget splits "<schema>.<table>.<column>" into a Spec. Each part must be a plain identifier; the full check is Validate.
func (Spec) FunctionName ¶
FunctionName is the unqualified function name: <table>_nearest_<column>.