diffplan

package
v0.1.0 Latest Latest
Warning

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

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

Documentation

Overview

Package diffplan is the declarative front door as a library: a parsed desired-state schema in, the routed convergence plan out. The CLI's diff command and orchestrators embedding pg-sprite share this one pipeline, so a stored report means the same thing no matter which caller produced it.

Callers own the boundary concerns: parse the desired file through statement.ParseDesired (refusals surface at the caller) and build the connection through dbconn.NewPool. Plan never writes the live table, but it is not read-only either — desired state is realized by execute-and-introspect on a rolled-back scratch schema, so the connection requirements on Plan apply.

Before a v1 module tag the Go API carries no compatibility promise: the JSON plan.Report is the stability boundary, the Go API follows at v1 (see docs/architecture.md).

Example (Plan)

Example_plan is the full library flow an orchestrator embeds: parse the desired-state schema, connect, and derive the routed convergence plan. It is compile-checked but not executed — Plan needs a live PostgreSQL database.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/block/pg-sprite/pkg/dbconn"
	"github.com/block/pg-sprite/pkg/diffplan"
	"github.com/block/pg-sprite/pkg/statement"
)

func main() {
	ctx := context.Background()

	// Parse refusals (inadmissible desired files) surface here, at the
	// boundary where the embedder can render them.
	ds, err := statement.ParseDesired(
		"CREATE TABLE events (id bigint PRIMARY KEY, name varchar(50) NOT NULL);\n" +
			"CREATE INDEX events_name_idx ON events (name);")
	if err != nil {
		log.Print(err)
		return
	}

	// Plan is not read-only: the desired DDL runs in an always-rolled-back
	// scratch schema, so connect read-write (not a hot standby) as a role
	// with CREATE on the target database. The live table is never written.
	pool, err := dbconn.NewPool(ctx, dbconn.Config{URL: "postgres://engine@localhost:5432/app"})
	if err != nil {
		log.Print(err)
		return
	}
	defer pool.Close()

	report, err := diffplan.Plan(ctx, pool, diffplan.Request{Schema: "public", Desired: ds})
	if err != nil {
		log.Print(err)
		return
	}

	// Disposition says whether the whole plan can execute; each statement
	// carries its route and the engine's canonical SQL rendering.
	fmt.Println(report.Disposition)
	for _, st := range report.Statements {
		fmt.Println(st.Route, st.SQL)
	}
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Plan

func Plan(ctx context.Context, pool *pgxpool.Pool, req Request) (plan.Report, error)

Plan derives the ordered, classified, and routed convergence plan for the desired schema against the live database: introspect the live table, derive the changes (the full qualified desired schema when the table does not exist yet), classify each change with live-column facts, route the set, and stamp the report with the server version and fingerprint.

Plan needs more than a read-only connection: desired state is realized by executing the desired DDL in a scratch schema inside a transaction that is always rolled back, so the pool must connect read-write (not a hot standby) as a role with CREATE privilege on the target database. The live table is introspected only — never written. Plan does not close the pool; one pool serves any number of calls.

Types

type Request

type Request struct {
	// Schema is the target schema the desired table lives in.
	Schema string
	// Desired is the parsed desired-state schema for the table.
	Desired statement.DesiredSchema
}

Request names the inputs to Plan. Zero-value fields are invalid: the schema must be set, and the desired state must come from statement.ParseDesired — the zero DesiredSchema is refused.

Jump to

Keyboard shortcuts

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