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

sqldb

package
v0.9.0 Latest Latest
Warning

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

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

Documentation

Overview

Package sqldb opens the app's SQL database, a MySQL database of its own. The app never holds a credential: Open connects to the runner's socket, and the runner logs in to the database as the app's own user, whose grants reach only the app's database. There is no DSN and no password anywhere in the app.

The permission list declares the database as a data source:

data:
  - source: sqldb
    classes: [internal]

The app's tables come from its schema changes, never from its code. Write the next change in the draft .aicoded/migration.sql, which stays out of git and goes to the platform with aicoded publish; aicoded dev, aicoded check and the platform apply it as the database's owner. The app's own user reads and writes rows only, and aicoded check refuses CREATE, ALTER, DROP, RENAME and TRUNCATE in app code (E-LINT-013).

Rules:

  • Open the database once, in OnStart, and share the *sql.DB with the pages through the app's deps package.
  • Pass every value with a ? placeholder; never join values into SQL.
  • Run statements that belong together in a transaction, and send mail about them only after it commits.
  • One statement runs per call, and times are read and written in UTC.

Every query and transaction gets a trace span that names only the statement's first keyword, never its text or its values.

A test opens the test database that aicoded check makes, with the app's tables, through package aicoded.dev/framework/sqldb/sqltest.

Read more in the guides docs/guides/sql-database.md and docs/guides/schema-changes.md and the task docs/tasks/list-from-database.md, which aicoded explain and the MCP tool howto print as guides/sql-database, guides/schema-changes and tasks/list-from-database.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Open

func Open(ctx context.Context) (*sql.DB, error)

Open returns the pool of connections to the app's database. Times are read and written in UTC, one statement runs per call, and statements with arguments are always prepared. Open fails with E-MAN-010 when aicoded.yaml does not declare the data source sqldb.

Example

Open the database once, in OnStart, and keep the *sql.DB in the app's deps for every page. Its tables come from the app's draft of schema changes, .aicoded/migration.sql, such as

CREATE TABLE notes (
	id BIGINT AUTO_INCREMENT PRIMARY KEY,
	owner VARCHAR(512) COLLATE utf8mb4_0900_bin NOT NULL,
	title VARCHAR(200) NOT NULL,
	created DATETIME NOT NULL
);
package main

import (
	"context"
	"database/sql"

	"aicoded.dev/framework/sqldb"
)

var db *sql.DB // the database Open returned in OnStart

func main() {
	onStart := func(ctx context.Context) error {
		var err error
		db, err = sqldb.Open(ctx)
		return err
	}
	_ = onStart
}
Example (Query)

Pass every value with a ? placeholder, here to list the viewer's notes in a page's Data.

package main

import (
	"context"
	"database/sql"
	"fmt"

	"aicoded.dev/framework/auth"
)

var db *sql.DB // the database Open returned in OnStart

func main() {
	data := func(ctx context.Context) error {
		rows, err := db.QueryContext(ctx, "SELECT id, title FROM notes WHERE owner = ? ORDER BY id", auth.Viewer(ctx).Subject)
		if err != nil {
			return err
		}
		defer rows.Close()
		for rows.Next() {
			var id int64
			var title string
			if err := rows.Scan(&id, &title); err != nil {
				return err
			}
			fmt.Println(id, title)
		}
		return rows.Err()
	}
	_ = data
}
Example (Transaction)

Run statements that belong together in a transaction, here in a form's Process hook.

package main

import (
	"context"
	"database/sql"
	"time"

	"aicoded.dev/framework/auth"
)

var db *sql.DB

func main() {
	process := func(ctx context.Context) error {
		owner := auth.Viewer(ctx).Subject
		tx, err := db.BeginTx(ctx, nil)
		if err != nil {
			return err
		}
		defer func() { _ = tx.Rollback() }() // does nothing after Commit
		_, err = tx.ExecContext(ctx, "INSERT INTO notes (owner, title, created) VALUES (?, ?, ?)", owner, "Quarterly review", time.Now())
		if err != nil {
			return err
		}
		_, err = tx.ExecContext(ctx, "UPDATE owners SET notes = notes + 1 WHERE owner = ?", owner)
		if err != nil {
			return err
		}
		return tx.Commit()
	}
	_ = process
}

Types

This section is empty.

Directories

Path Synopsis
Package sqltest opens, in an app's tests, the test database that aicoded check makes for the app: a database of its own with the app's tables, which the tests reach as the app's data user, who reads and writes rows and changes no table.
Package sqltest opens, in an app's tests, the test database that aicoded check makes for the app: a database of its own with the app's tables, which the tests reach as the app's data user, who reads and writes rows and changes no table.

Jump to

Keyboard shortcuts

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