Help us shape the future of Go! Take the 2026 Go Developer Survey

postgres

package module
v0.1.0-preview.14 Latest Latest
Warning

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

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

Documentation

Overview

Package postgres is the PostgreSQL store: it writes finalized records and their initial event, reads records back, runs the contract's text search, and records injections, all as the application role inside a transaction that first declared its bounds.

It runs against a schema the .NET migrator applied (ExperienceSchemaMigrator.MigrateAsync, then ApplyApplicationRolePrivilegesAsync with row-level security on, or the contract's two privileges files) and never creates or alters a schema object. The bounds, the search and the injection record are the contract's SQL files, embedded and run as written: only their @name placeholders are spelled the way the driver spells them ($1, $2, ...).

Index

Constants

View Source
const (
	DeclareBoundsSQL   = "declare-bounds.sql"
	SearchSQL          = "search-experience-text.sql"
	RecordInjectionSQL = "record-injection.sql"
)

The contract's SQL files, as this package embeds them.

Variables

View Source
var ErrSealed = errors.New("the record is sealed (payload_version 2) and a contract 1.x port cannot read it")

ErrSealed is Get's answer for a record that exists in the scope but is sealed (payload_version 2, crypto-shredding), which a contract 1.x port cannot read. A record that does not exist is (nil, nil).

Functions

func ContractSQL

func ContractSQL(name string) (string, error)

ContractSQL is one of the contract's SQL files, as this package embeds it (DeclareBoundsSQL, SearchSQL, RecordInjectionSQL). A test keeps the embedded copies identical to contract/sql/.

Types

type Beginner

type Beginner interface {
	Begin(ctx context.Context) (pgx.Tx, error)
}

Beginner starts the transactions the store runs in. *pgxpool.Pool, *pgx.Conn and pgx.Tx (each transaction is then a savepoint inside it) all satisfy it. Every connection it hands out must be the application role's.

type Statement

type Statement struct {
	SQL   string
	Names []string
}

Statement is a SQL text with its @name placeholders numbered for the driver, and the parameter each number stands for.

func ToDriverPlaceholders

func ToDriverPlaceholders(sql string) Statement

ToDriverPlaceholders numbers the contract's @name placeholders as $1, $2, ... (one number per distinct name). Only code is rewritten: a -- or /* */ comment, a single-quoted literal (E” escapes included), a double-quoted identifier and a dollar-quoted string are kept as written, so a parameter named only inside one of them is never asked for. An @ followed by a letter or _ in code is always a placeholder, so PostgreSQL's prefix @ operator must be written with a space after it.

func (Statement) Args

func (s Statement) Args(values map[string]any) ([]any, error)

Args are the statement's positional arguments, taken by name from values. A name with no value is an error.

type Store

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

Store keeps records in PostgreSQL through pgx. Each operation runs one transaction, begun on the connection source the host gave it. A Store is safe for concurrent use exactly when its source is: a *pgxpool.Pool is, a single *pgx.Conn or pgx.Tx is not (use it from one goroutine at a time).

func NewStore

func NewStore(db Beginner) (*Store, error)

NewStore is a store that runs its transactions on db, which the host controls (and closes).

func Open

func Open(ctx context.Context, connString string) (*Store, error)

Open is a store on a new connection pool for a connection string (as the application role). Close it with Close.

func (*Store) Close

func (s *Store) Close()

Close closes the pool Open made. It does nothing for a store on a source the host gave NewStore.

func (*Store) Get

func (s *Store) Get(ctx context.Context, bounds ae.AuthorizationBounds, scope ae.Scope, id ae.UUID) (*ae.ExperienceRecord, error)

Get reads one record in exactly scope (every scope field equal, an unset one unset), within bounds. It returns (nil, nil) when there is none (or it was deleted), and ErrSealed when it is sealed (payload_version 2, which a contract 1.x port cannot read).

func (*Store) InsertFinalized

func (s *Store) InsertFinalized(ctx context.Context, bounds ae.AuthorizationBounds, finalized *ae.FinalizedExperience,
	actor string, recordedAt *time.Time) error

InsertFinalized writes a finalized record in its final state at revision 1, and the initial lifecycle event that took it there, in one transaction. actor is the authorizing principal; recordedAt defaults to now. The event must be the record's own (its experience ID, its status and its revision); anything else is refused before writing.

func (*Store) InsertRecord

func (s *Store) InsertRecord(ctx context.Context, bounds ae.AuthorizationBounds, record *ae.ExperienceRecord) error

InsertRecord writes one record's row exactly as given, with no lifecycle event. It is for seeding and tests: a record this package finalizes is written with InsertFinalized, or it has no history.

func (*Store) RecordInjection

func (s *Store) RecordInjection(ctx context.Context, bounds ae.AuthorizationBounds, scope ae.Scope,
	experienceIDs []ae.UUID, injectedAt ae.Instant) error

RecordInjection records that experienceIDs were injected in scope at injectedAt: it runs sql/record-injection.sql (contract 1.4) once, in one transaction that declared bounds. Only a record live in exactly scope gets a row (one borrowed through a grant, or in another scope, is skipped by the statement); the instant is truncated to whole microseconds and clamped to the database clock. It refuses more than agentexperience.MaxRecordInjectionIDs IDs or a nil one, and a scope outside the bounds (agentexperience.ErrAuthorizationDenied); otherwise a failure is the driver's (insufficient_privilege, 42501, until the role holds the grants of sql/application-role-privileges-1.4.sql). The agent integration calls it in the background, fail-open.

func (*Store) Search

func (s *Store) Search(ctx context.Context, bounds ae.AuthorizationBounds, parameters ae.SearchParameters) ([]ae.SearchRow, error)

Search runs sql/search-experience-text.sql and returns its rows in the order returned, each relevance widened from real. A sealed row (payload_version 2) is skipped. Rank them with agentexperience.Rank.

Directories

Path Synopsis
pgtest module

Jump to

Keyboard shortcuts

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