Xo is experimental. The source is now public on GitHub, or try Xo in your browser.
Menu · sql

Docs

std/sql

On this page

Index

Types

SqlValue

enum SqlValue {
  Null
  Integer(n: Int)
  Text(s: Str)
  Real(f: Float)
  Flag(b: Bool)
  At(t: Time)
  Blob(b: Bytes)
  JsonText(s: Str)
  Array(items: List[SqlValue])
}

A query parameter. $1 is args[0].

Source: std/sql.xo:19

Isolation

enum Isolation {
  Default
  ReadUncommitted
  ReadCommitted
  RepeatableRead
  Serializable
}

A transaction’s isolation level (Go’s sql.IsolationLevel, the four of standard SQL); Default is the server’s own.

Source: std/sql.xo:50

SqlErr

enum SqlErr {
  Syntax(msg: Str)
  Constraint(msg: Str, code: Str, name: Str)
  Param(msg: Str)
  NoTable(name: Str)
  NoRows
  NoColumn(name: Str)
  Mismatch(column: Str, msg: Str)
  Conn(msg: Str)
  Driver(msg: Str)
  Server(code: Str, msg: Str)
  TxDone
  Closed
  Canceled
}

Source: std/sql.xo:58

SqlErr.display

fn (e: SqlErr) display() -> Str

Plain text (decision 0358): syntax error: MSG, MSG for a Constraint, Param or Driver, no such table: NAME, no rows in result set, no such column: NAME, column COL: MSG, connection: MSG, MSG (SQLSTATE CODE), transaction already committed or rolled back, database is closed, canceled.

Source: std/sql.xo:89

ExecResult

struct ExecResult {
  rows_affected: Int
  last_insert_id: Int
}

Source: std/sql.xo:91

Db

struct Db[fx: Effects] {}

Source: std/sql.xo:97

Db.query

fn (d: Db) query(q: Str, args: List[SqlValue] = []) -> List[Row] ! SqlErr uses net.dial

Source: std/sql.xo:113

Db.rows

fn (d: Db) rows(q: Str, args: List[SqlValue] = []) -> Rows ! SqlErr uses net.dial

query as a cursor: the rows are read from the connection as next asks (the Postgres driver; the in memory database and the Go backend read the result whole), so a result larger than memory can be walked. The connection stays taken until next returns None or an error, or close; use each or defer rows.close().

Source: std/sql.xo:119

Db.each

fn (d: Db) each(q: Str, args: List[SqlValue], f: fn(Row) -> () ! SqlErr) -> () ! SqlErr uses net.dial

rows, calling f on each row and closing in every path; an error from f ends the walk and is returned.

Source: std/sql.xo:122

Db.copy_from

fn (d: Db) copy_from(table: Str, columns: List[Str], rows: fn() -> List[SqlValue]? ! SqlErr) -> Int ! SqlErr uses net.dial

Loads rows with COPY FROM STDIN in the text format (decision 0479, pgx’s CopyFrom): rows is called until it returns None, each row a list of values in the order of columns; the result is the number of rows copied. An error from rows cancels the COPY (the server rolls it back) and is returned. table and columns are identifiers, quoted by the driver (quote_ident); values are never interpolated. The in memory database inserts the rows one by one; a driver without COPY returns Driver.

Source: std/sql.xo:131

Db.query_one

fn (d: Db) query_one(q: Str, args: List[SqlValue] = []) -> Row ! SqlErr uses net.dial

Source: std/sql.xo:132

Db.exec

fn (d: Db) exec(q: Str, args: List[SqlValue] = []) -> ExecResult ! SqlErr uses net.dial

Source: std/sql.xo:133

Db.query_as

fn (d: Db) query_as[T: SqlRow](q: Str, args: List[SqlValue] = []) -> List[T] ! SqlErr uses net.dial

query with every row decoded into T (derive SqlRow, std.md 10.4).

Source: std/sql.xo:135

Db.query_one_as

fn (d: Db) query_one_as[T: SqlRow](q: Str, args: List[SqlValue] = []) -> T ! SqlErr uses net.dial

query_one with the row decoded into T.

Source: std/sql.xo:137

Db.begin

fn (d: Db) begin(isolation: Isolation = Isolation.Default, read_only: Bool = false) -> Tx ! SqlErr uses net.dial

A transaction (Go’s DB.BeginTx): isolation and read_only are Go’s sql.TxOptions. A driver’s connection gets SET TRANSACTION ... with them right after BEGIN (nothing for the defaults); the in memory database is serializable whatever the level, and refuses a write in a read only transaction with Server(“25006”, …), as Postgres does.

Source: std/sql.xo:143

Db.ping

fn (d: Db) ping() -> () ! SqlErr uses net.dial

Source: std/sql.xo:144

Db.close

fn (d: Db) close() -> () ! SqlErr

Source: std/sql.xo:145

Tx

struct Tx[fx: Effects] {}

Source: std/sql.xo:98

Tx.query

fn (t: Tx) query(q: Str, args: List[SqlValue] = []) -> List[Row] ! SqlErr uses net.dial

Source: std/sql.xo:147

Tx.rows

fn (t: Tx) rows(q: Str, args: List[SqlValue] = []) -> Rows ! SqlErr uses net.dial

Db.rows inside the transaction: the transaction’s connection is busy until the cursor ends or is closed.

Source: std/sql.xo:150

Tx.each

fn (t: Tx) each(q: Str, args: List[SqlValue], f: fn(Row) -> () ! SqlErr) -> () ! SqlErr uses net.dial

Source: std/sql.xo:151

Tx.copy_from

fn (t: Tx) copy_from(table: Str, columns: List[Str], rows: fn() -> List[SqlValue]? ! SqlErr) -> Int ! SqlErr uses net.dial

Source: std/sql.xo:152

Tx.query_one

fn (t: Tx) query_one(q: Str, args: List[SqlValue] = []) -> Row ! SqlErr uses net.dial

Source: std/sql.xo:153

Tx.exec

fn (t: Tx) exec(q: Str, args: List[SqlValue] = []) -> ExecResult ! SqlErr uses net.dial

Source: std/sql.xo:154

Tx.query_as

fn (t: Tx) query_as[T: SqlRow](q: Str, args: List[SqlValue] = []) -> List[T] ! SqlErr uses net.dial

Source: std/sql.xo:155

Tx.query_one_as

fn (t: Tx) query_one_as[T: SqlRow](q: Str, args: List[SqlValue] = []) -> T ! SqlErr uses net.dial

Source: std/sql.xo:156

Tx.commit

fn (t: Tx) commit() -> () ! SqlErr uses net.dial

Source: std/sql.xo:157

Tx.rollback

fn (t: Tx) rollback() -> () ! SqlErr uses net.dial

Source: std/sql.xo:158

Row

struct Row {}

Source: std/sql.xo:99

Row.columns

fn (r: Row) columns() -> List[Str]

Source: std/sql.xo:169

Row.decode

fn (r: Row) decode[T: SqlRow]() -> T ! SqlErr

Decodes the row into a struct with derive SqlRow: each field from the column of the same name (std.md 10.4).

Source: std/sql.xo:172

Row.value

fn (r: Row) value(name: Str) -> SqlValue ! SqlErr

The column’s value as the driver read it (pgx’s Rows.Values, one column; NoColumn for an unknown name).

Source: std/sql.xo:175

Row.is_null

fn (r: Row) is_null(name: Str) -> Bool ! SqlErr

Source: std/sql.xo:176

Row.int

fn (r: Row) int(name: Str) -> Int ! SqlErr

Source: std/sql.xo:177

Row.str

fn (r: Row) str(name: Str) -> Str ! SqlErr

Source: std/sql.xo:178

Row.float

fn (r: Row) float(name: Str) -> Float ! SqlErr

Source: std/sql.xo:179

Row.bool

fn (r: Row) bool(name: Str) -> Bool ! SqlErr

Source: std/sql.xo:180

Row.time

fn (r: Row) time(name: Str) -> Time ! SqlErr

Source: std/sql.xo:181

Row.int_opt

fn (r: Row) int_opt(name: Str) -> Int? ! SqlErr

Source: std/sql.xo:182

Row.str_opt

fn (r: Row) str_opt(name: Str) -> Str? ! SqlErr

Source: std/sql.xo:183

Row.float_opt

fn (r: Row) float_opt(name: Str) -> Float? ! SqlErr

Source: std/sql.xo:184

Row.bool_opt

fn (r: Row) bool_opt(name: Str) -> Bool? ! SqlErr

Source: std/sql.xo:185

Row.time_opt

fn (r: Row) time_opt(name: Str) -> Time? ! SqlErr

Source: std/sql.xo:186

Row.bytes

fn (r: Row) bytes(name: Str) -> Bytes ! SqlErr

Source: std/sql.xo:187

Row.bytes_opt

fn (r: Row) bytes_opt(name: Str) -> Bytes? ! SqlErr

Source: std/sql.xo:188

Row.json

fn (r: Row) json[T: Json](name: Str) -> T ! SqlErr

A json or jsonb column (or text) decoded into T; a decode error is Mismatch(column, msg).

Source: std/sql.xo:191

Row.ints

fn (r: Row) ints(name: Str) -> List[Int] ! SqlErr

An array of integers; a NULL element is Mismatch.

Source: std/sql.xo:193

Row.strs

fn (r: Row) strs(name: Str) -> List[Str] ! SqlErr

Source: std/sql.xo:194

Row.items

fn (r: Row) items(name: Str) -> List[SqlValue] ! SqlErr

An array’s elements as values.

Source: std/sql.xo:196

Rows

struct Rows[fx: Effects] {}

A result read row by row (decision 0479, Go’s *sql.Rows): holds a connection from rows to the last row or close.

Source: std/sql.xo:102

Rows.columns

fn (r: Rows) columns() -> List[Str]

Source: std/sql.xo:160

Rows.next

fn (r: Rows) next() -> Row? ! SqlErr uses net.dial

The next row, None after the last (the connection is then released).

Source: std/sql.xo:162

Rows.next_as

fn (r: Rows) next_as[T: SqlRow]() -> T? ! SqlErr uses net.dial

next decoded into T (derive SqlRow).

Source: std/sql.xo:164

Rows.close

fn (r: Rows) close() uses net.dial

Reads and discards the rest of the result and releases the connection; idempotent.

Source: std/sql.xo:167

Driver

interface Driver[fx: Effects] {
  fn connect(self, net: Net, dsn: Str) -> DriverConn[fx] ! SqlErr uses (net.dial, fx)
}

A database driver written in Xo (decision 0278): opened with open_driver, which gives it std/sql’s pool, transactions, and cancellation. It dials through the Net it is given.

Source: std/sql.xo:201

DriverConn

interface DriverConn[fx: Effects] {
  fn query(self, q: Str, args: List[SqlValue]) -> DriverRows[fx] ! SqlErr uses (net.dial, fx)
  fn exec(self, q: Str, args: List[SqlValue]) -> ExecResult ! SqlErr uses (net.dial, fx)
  fn begin(self) -> () ! SqlErr uses (net.dial, fx)
  fn commit(self) -> () ! SqlErr uses (net.dial, fx)
  fn rollback(self) -> () ! SqlErr uses (net.dial, fx)
  fn ping(self) -> () ! SqlErr uses (net.dial, fx)
  fn copy_from(self, table: Str, columns: List[Str], rows: fn() -> List[SqlValue]? ! SqlErr) -> Int ! SqlErr uses (net.dial, fx)
  fn close(self) uses (net.dial, fx)
  fn is_broken(self) -> Bool
}

One connection of a Driver, used by one task at a time. Its waits are cancellation points that return Canceled.

Source: std/sql.xo:207

DriverRows

struct DriverRows[fx: Effects] {
  columns: List[Str]
  rows: List[List[SqlValue]]
  cursor: DriverCursor[fx]? = None
}

The result of DriverConn.query: column names and rows of values. A driver may return a few rows (or none) and a cursor for the rest (decision 0479): Db.rows reads them as asked, Db.query reads them all.

Source: std/sql.xo:224

DriverCursor

interface DriverCursor[fx: Effects] {
  fn next(self) -> List[SqlValue]? ! SqlErr uses (net.dial, fx)
  fn rest(self) -> List[List[SqlValue]] ! SqlErr uses (net.dial, fx)
  fn close(self) uses (net.dial, fx)
}

The rest of a result still on the connection. The connection is not used again until the cursor is read to the end or closed.

Source: std/sql.xo:232

Functions

null

fn null() -> SqlValue

Source: std/sql.xo:34

int

fn int(n: Int) -> SqlValue

Source: std/sql.xo:35

str

fn str(s: Str) -> SqlValue

Source: std/sql.xo:36

float

fn float(f: Float) -> SqlValue

Source: std/sql.xo:37

bool

fn bool(b: Bool) -> SqlValue

Source: std/sql.xo:38

time

fn time(t: Time) -> SqlValue

Source: std/sql.xo:39

bytes

fn bytes(b: Bytes) -> SqlValue

Source: std/sql.xo:40

json

fn json[T: Json](v: T) -> SqlValue

JsonText of json.encode_str(v).

Source: std/sql.xo:42

array

fn array(items: List[SqlValue]) -> SqlValue

Source: std/sql.xo:43

quote_ident

fn quote_ident(name: Str) -> Str

An SQL identifier in double quotes, a double quote doubled (Postgres’s quote_ident, pgx’s Identifier.Sanitize).

Source: std/sql.xo:46

open

fn open(net: Net, driver: Str, dsn: Str, max_open: Int = 10, max_idle: Int = 2, max_lifetime: Duration = 30m, roots: Bytes = b"") -> Db ! SqlErr uses net.dial

Opens a database: “postgres” (decision 0278; roots is PEM for sslmode verify-ca and verify-full) natively. max_open bounds concurrent operations and open transactions (waiting is a cancellation point), max_idle and max_lifetime are passed to the driver.

Source: std/sql.xo:108

memory

fn memory(schema: Str = "") -> Db ! SqlErr

An in memory database, optionally created with schema (; separated statements). Needs no capability.

Source: std/sql.xo:111

open_driver

fn open_driver[fx: Effects](net: Net, d: Driver[fx], dsn: Str, max_open: Int = 10, max_idle: Int = 2, max_lifetime: Duration = 30m) -> Db[fx] ! SqlErr uses (net.dial, fx)

A Db over d: max_open connections at most (operations and open transactions; waiting is a cancellation point), max_idle kept open when unused, each closed after max_lifetime. Connects once before it returns, so a wrong password or host fails here.

Source: std/sql.xo:245

↑ index