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

database

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package database holds the named sql connections a phpscript runtime resolves through. It is a copy of the provider in github.com/titpetric/platform, which lives in an internal package and cannot be imported, so that a provider can be scoped to a virtual host instead of being process global.

Index

Constants

This section is empty.

Variables

View Source
var ErrReadOnly = errors.New("database is read-only")

ErrReadOnly is what a refusal by a read-only client matches with errors.Is. The runtime surfaces the refusal to PHP as a thrown exception, so a script catches it like any other database error.

Functions

func Open

func Open(driver, dsn string) (*sqlx.DB, error)

Open creates a *sqlx.DB from a driver name and a DSN. It is the default open function of DatabaseProvider.

The connection is not instrumented. Query level spans belong to the driver, not to the provider, so a caller that wants them supplies an instrumented open function instead.

func Register

func Register(rt *runner.Runtime)

Register installs the Database and Database\Migrate bindings on rt.

func RegisterMigrate

func RegisterMigrate(rt *runner.Runtime)

RegisterMigrate installs the Database\Migrate binding.

Types

type Database

type Database struct {
	Bridge *client.Bridge
	ID     string

	// IsReadonly restricts the client to statements that only read. It is a
	// property of the client, not of the connection: PHP reads and writes it as
	// `$db->is_readonly`, and it lives as long as the client does, which for a
	// served request is the request.
	//
	// It refuses insert(), replace() and update() outright, and refuses any
	// statement passed to query(), get() or get_all() that does not start with
	// a read-only keyword (see readOnlyStatements). Transactions, connection
	// pinning and the result accessors stay available, since a read-only
	// transaction is a read.
	//
	// The restriction is a boundary for the code holding this client, not a
	// sandbox around the script: the script that set it can unset it. A
	// connection that must not write belongs to a database user without the
	// grant to, and this marks the code that must not write.
	IsReadonly bool
	// contains filtered or unexported fields
}

Database adds request tracing to the database binding.

func (*Database) Begin

func (b *Database) Begin(ctx context.Context) (any, error)

Begin starts a transaction and opens the span measuring it. The span stays open until Commit or Rollback, so a transaction is one region in the trace rather than an open marker and a close marker to pair up.

func (*Database) Close

func (b *Database) Close(ctx context.Context) (any, error)

Close releases an exclusive connection back to the pool.

func (*Database) Commit

func (b *Database) Commit(ctx context.Context) (any, error)

Commit commits the active transaction and ends its span.

func (*Database) Connect

func (b *Database) Connect(ctx context.Context) (any, error)

Connect reserves an exclusive connection from the pool.

func (*Database) Get

func (b *Database) Get(ctx context.Context, query string, args ...any) (any, error)

Get returns the first result row.

Rows reach PHP as the bridge produced them, a map[string]any per row and a []map[string]any per result set, rather than being copied into a *model.Array. The VM reads both natively: foreach walks them, $row["col"] indexes them, and $row["extra"] = 1 writes to them, since a Go map is a reference type. The copy cost two allocations plus an interface box per column on every row of every query.

The one thing a map does not carry is column order, and neither did the *model.Array: the bridge's map had already lost it, so `foreach ($row as $column => $value)` has always produced an arbitrary order. It is now arbitrary per iteration rather than fixed per row; scripts that need a stable order should name their columns in the SELECT and index them.

func (*Database) GetAll

func (b *Database) GetAll(ctx context.Context, query string, args ...any) (any, error)

GetAll returns all result rows. See Get for the row representation.

func (*Database) Insert

func (b *Database) Insert(ctx context.Context, table string, value any) (any, error)

Insert inserts a dynamically typed named value.

func (*Database) InsertID

func (b *Database) InsertID(ctx context.Context) (any, error)

InsertID returns the ID generated by the last insert.

func (*Database) Query

func (b *Database) Query(ctx context.Context, query string, args ...any) (any, error)

Query executes a statement with dynamically typed arguments.

func (*Database) Replace

func (b *Database) Replace(ctx context.Context, table string, value any) (any, error)

Replace replaces a row using a dynamically typed named value.

func (*Database) Rollback

func (b *Database) Rollback(ctx context.Context) (any, error)

Rollback rolls back the active transaction and ends its span.

func (*Database) RowsAffected

func (b *Database) RowsAffected(ctx context.Context) (any, error)

RowsAffected returns the affected row count from the last write.

func (*Database) SetID

func (b *Database) SetID(id string)

SetID records the PHP variable receiving this constructed client.

func (*Database) Update

func (b *Database) Update(ctx context.Context, table string, value any, keyColumns ...any) (any, error)

Update updates a row using dynamically typed named values and key columns.

type DatabaseMigrate

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

DatabaseMigrate loads and runs SQL migrations against a platform database.

func (*DatabaseMigrate) Load

func (m *DatabaseMigrate) Load(pattern string) error

Load reads migrations matching pattern from the runtime source filesystem.

func (*DatabaseMigrate) Run

func (m *DatabaseMigrate) Run(ctx context.Context) error

Run applies the loaded migrations. It is one span rather than one per file: migrations run at startup, where what matters is how long the schema took and whether it failed, not a row per statement.

type DatabaseOption

type DatabaseOption struct {
	MaxOpenConns int
	MaxIdleConns int
}

DatabaseOption configures database connection pooling settings.

func (*DatabaseOption) Apply

func (o *DatabaseOption) Apply(client *sqlx.DB)

Apply applies the database option settings to a database connection.

type DatabaseProvider

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

DatabaseProvider holds a list of named sql connection credentials.

func New

func New(environment []string) *DatabaseProvider

New returns a provider holding only the connections named in environment, in PLATFORM_DB_<NAME>=<dsn> form, plus the built-in default. A provider built this way sees nothing but what it was given, which is what keeps one virtual host out of another's databases.

func NewDatabaseProvider

func NewDatabaseProvider(open func(string, string) (*sqlx.DB, error)) *DatabaseProvider

NewDatabaseProvider will allocate a valid `*DatabaseProvider` and return it.

func (*DatabaseProvider) Connect

func (r *DatabaseProvider) Connect(ctx context.Context, names ...string) (*sqlx.DB, error)

Connect issues a PingContext to verify a live connection before returning. The context is used to propagate tracing detail so ping is grouped correctly.

func (*DatabaseProvider) List

func (r *DatabaseProvider) List() []string

List will return the list of credential names.

func (*DatabaseProvider) Open

func (r *DatabaseProvider) Open(_ context.Context, names ...string) (*sqlx.DB, error)

Open is the same as sql.Open. It creates a client from a named connection.

func (*DatabaseProvider) Register

func (r *DatabaseProvider) Register(name string, config string)

Register will add a new named credential into the provider. The function is not concurrency safe, database credentials can't be changed during the lifetime of the provider.

type Provider

type Provider = model.DatabaseProvider

Provider is what a runtime resolves named connections through. The interface is declared in model, which a runtime can name in its options without depending on this package.

var Default Provider = New(os.Environ())

Default is the provider used when a runtime's options name none. It is the process environment, which is what a CLI run has.

Jump to

Keyboard shortcuts

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