db
One interface shared by the database engines, schema migrations and a connection pool.
import db
Every database engine has its own package: db/sqlite, db/mysql, db/postgres, for key and value db/redis, and for search db/meilisearch and db/elasticsearch, which also answers SQL queries through Connection. This package gives the Connection interface that the three SQL engines implement; write your code against it and changing engine is one line.
Migrations move the database schema along with the code: every change has a number and MigrateUp applies only the ones not applied yet. Never paste a value a user typed straight into SQL; send it through QuoteLiteral or as a prepared parameter.
Types
Pool
struct Pool| Name | Type | Description |
|---|---|---|
conns | Vector | The connections. |
taken | Vector | Which connections are taken. |
limit | int = 0 | The greatest number of connections. |
import db
import db.sqlite
func main:
mut pool := db.NewPool(2)
repeat 3:
println db.Add(pool, sqlite.Conn(sqlite.Open(":memory:")))
end
println db.Size(pool), db.Idle(pool), db.InUse(pool)
one := db.Acquire(pool)
two := db.Acquire(pool)
three := db.Acquire(pool)
println db.Leased(one), db.Leased(three), three == db.NO_LEASE
println db.Idle(pool), db.InUse(pool)
c := db.Conn(pool, one)
println db.QueryInt(c, "SELECT 6 * 7")
db.Release(pool, one)
db.Release(pool, two)
println db.Idle(pool), db.DropDead(pool)
db.CloseAll(pool)
db.Free(pool)
endRows
interface Rowsnext, text, int, close and the like.import db
import db.sqlite
func report(c: dyn db.Connection):
println c.Kind(), c.Ok(), c.Ping()
_ := c.Exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, score REAL)")
_ := c.Exec("INSERT INTO users (name, score) VALUES (" + c.Quote("O'Brien") + ", 7.5)")
_ := c.Exec("INSERT INTO users (name, score) VALUES ('Maryam', 9)")
println c.LastInsertId(), c.Changes()
rows := c.Query("SELECT id, name, score FROM users ORDER BY id")
println rows.Ok(), rows.ColumnCount(), rows.ColumnName(1)
until rows.Next():
println rows.Int(0), rows.Text(1), rows.Float(2), rows.Int64(0), rows.IsNull(2), rows.ColumnType(1)
end
_ := rows.Close()
tx := c.Begin()
println tx.Ok()
_ := tx.Exec("UPDATE users SET score = 0")
txrows := tx.Query("SELECT SUM(score) FROM users")
_ := txrows.Next()
println txrows.Float(0)
_ := txrows.Close()
_ := tx.Rollback()
tx2 := c.Begin()
_ := tx2.Exec("DELETE FROM users WHERE id = 1")
_ := tx2.Commit()
println db.QueryInt(c, "SELECT COUNT(*) FROM users"), db.QueryInt64(c, "SELECT MAX(id) FROM users")
println db.QueryFloat(c, "SELECT score FROM users"), db.QueryText(c, "SELECT name FROM users")
println db.CountRows(c, "SELECT * FROM users")
println db.Run(c, "INSERT INTO users (name) VALUES ('Ali')"), db.Run(c, "INSERT INTO nowhere VALUES (1)")
println c.Error()
mut stmts := Vector {} as Vector<str>
stmts.push("INSERT INTO users (name) VALUES ('Sara')")
stmts.push("INSERT INTO users (name) VALUES ('Reza')")
println db.RunAll(c, stmts)
stmts.push("INSERT INTO nowhere VALUES (1)")
println db.InTx(c, stmts), db.QueryInt(c, "SELECT COUNT(*) FROM users")
println db.QuoteLiteral("it's")
_ := c.Close()
end
func main:
report(sqlite.Conn(sqlite.Open(":memory:")))
println db.SQLITE, db.MYSQL, db.POSTGRES
println db.TYPE_NULL, db.TYPE_INT, db.TYPE_FLOAT, db.TYPE_TEXT, db.TYPE_BLOB
endTx
interface Txexec, query, commit and rollback.The example for this item is shown with the ones above: db-Connection.salam
Connection
interface ConnectionConnect of whichever engine.The example for this item is shown with the ones above: db-Connection.salam
Migration
struct Migration| Name | Type | Description |
|---|---|---|
version | int = 0 | The version number; migrations are applied in that order. |
name | str = "" | The name. |
up | str = "" | The SQL that applies it; separate several statements with ;. |
down | str = "" | The SQL that undoes it. |
import db
import db.sqlite
func main:
c := sqlite.Conn(sqlite.Open(":memory:"))
mut m := db.NewMigrator()
db.AddMigration(m, 1, "users", "CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT NOT NULL)", "DROP TABLE users")
db.AddMigration(m, 2, "posts", "CREATE TABLE posts (id INTEGER PRIMARY KEY, title TEXT); INSERT INTO posts (title) VALUES ('hello')", "DROP TABLE posts")
db.AddMigration(m, 3, "tags", "ALTER TABLE posts ADD COLUMN tag TEXT", "ALTER TABLE posts DROP COLUMN tag")
println db.MigrationCount(m), db.SchemaVersion(m, c), db.PendingCount(m, c)
println db.MigrateTo(m, c, 2)
println db.SchemaVersion(m, c), db.IsApplied(m, c, 2), db.IsApplied(m, c, 3)
println db.MigrateUp(m, c), db.SchemaVersion(m, c)
println db.MigrateUp(m, c)
println db.Rollback(m, c), db.SchemaVersion(m, c)
println db.MigrateTo(m, c, 0), db.SchemaVersion(m, c)
println db.QueryInt(c, "SELECT COUNT(*) FROM " + db.MIGRATION_TABLE)
db.FreeMigrator(m)
mut m2 := db.NewMigratorIn("app_versions")
db.AddMigration(m2, 1, "t", "CREATE TABLE t (x INTEGER)", "DROP TABLE t")
println db.EnsureTable(m2, c), db.MigrateUp(m2, c), m2.table
db.FreeMigrator(m2)
parts := db.SplitStatements("INSERT INTO t VALUES (1); SELECT ';' ; ")
println parts.len(), parts.get(1)
endMigrator
struct Migrator| Name | Type | Description |
|---|---|---|
items | Vector | The migrations. |
table | str = "" | The name of the version table. |
The example for this item is shown with the ones above: db-Migrate.salam
Constants and variables
NO_LEASE
const NO_LEASE: i32 = -1Acquire returns when no connection is free.The example for this item is shown with the ones above: db-Pool.salam
SQLITE
const SQLITE: str = "sqlite"The example for this item is shown with the ones above: db-Connection.salam
MYSQL
const MYSQL: str = "mysql"The example for this item is shown with the ones above: db-Connection.salam
POSTGRES
const POSTGRES: str = "postgres"The example for this item is shown with the ones above: db-Connection.salam
ELASTICSEARCH
const ELASTICSEARCH: str = "elasticsearch"The example for this item is shown with the ones above: db-Connection.salam
TYPE_NULL
const TYPE_NULL: i32 = 0The example for this item is shown with the ones above: db-Connection.salam
TYPE_INT
const TYPE_INT: i32 = 1The example for this item is shown with the ones above: db-Connection.salam
TYPE_FLOAT
const TYPE_FLOAT: i32 = 2The example for this item is shown with the ones above: db-Connection.salam
TYPE_TEXT
const TYPE_TEXT: i32 = 3The example for this item is shown with the ones above: db-Connection.salam
TYPE_BLOB
const TYPE_BLOB: i32 = 4The example for this item is shown with the ones above: db-Connection.salam
MIGRATION_TABLE
const MIGRATION_TABLE: str = "schema_migrations"The example for this item is shown with the ones above: db-Migrate.salam
Functions
NewPool
func NewPool(limit: int): PoolThe example for this item is shown with the ones above: db-Pool.salam
Add
func Add(p &: Pool, c: dyn Connection): boolThe example for this item is shown with the ones above: db-Connection.salam
Acquire
func Acquire(p &: Pool): intThe example for this item is shown with the ones above: db-Pool.salam
Leased
func Leased(lease: int): boolThe example for this item is shown with the ones above: db-Pool.salam
Conn
func Conn(p: Pool, lease: int): dyn ConnectionThe example for this item is shown with the ones above: db-Pool.salam
Release
func Release(p &: Pool, lease: int)The example for this item is shown with the ones above: db-Pool.salam
Size
func Size(p: Pool): intThe example for this item is shown with the ones above: db-Pool.salam
Idle
func Idle(p: Pool): intThe example for this item is shown with the ones above: db-Pool.salam
InUse
func InUse(p: Pool): intThe example for this item is shown with the ones above: db-Pool.salam
DropDead
func DropDead(p &: Pool): intThe example for this item is shown with the ones above: db-Pool.salam
CloseAll
func CloseAll(p &: Pool)The example for this item is shown with the ones above: db-Pool.salam
Free
func Free(p &: Pool)The example for this item is shown with the ones above: db-Migrate.salam
QueryInt
func QueryInt(c: dyn Connection, sql: str): intCOUNT and the like.The example for this item is shown with the ones above: db-Connection.salam
QueryInt64
func QueryInt64(c: dyn Connection, sql: str): i64The example for this item is shown with the ones above: db-Connection.salam
QueryFloat
func QueryFloat(c: dyn Connection, sql: str): f64The example for this item is shown with the ones above: db-Connection.salam
QueryText
func QueryText(c: dyn Connection, sql: str): strThe example for this item is shown with the ones above: db-Connection.salam
CountRows
func CountRows(c: dyn Connection, sql: str): intThe example for this item is shown with the ones above: db-Connection.salam
Run
func Run(c: dyn Connection, sql: str): boolThe example for this item is shown with the ones above: db-Connection.salam
RunAll
func RunAll(c: dyn Connection, stmts: Vector<str>): intThe example for this item is shown with the ones above: db-Connection.salam
InTx
func InTx(c: dyn Connection, stmts: Vector<str>): boolThe example for this item is shown with the ones above: db-Connection.salam
QuoteLiteral
func QuoteLiteral(s: str): str' escaped.The example for this item is shown with the ones above: db-Connection.salam
NewMigrator
func NewMigrator(): MigratorThe example for this item is shown with the ones above: db-Migrate.salam
NewMigratorIn
func NewMigratorIn(table: str): MigratorThe example for this item is shown with the ones above: db-Migrate.salam
FreeMigrator
func FreeMigrator(m &: Migrator)The example for this item is shown with the ones above: db-Migrate.salam
AddMigration
func AddMigration(m &: Migrator, version: int, name: str, up: str, down: str)The example for this item is shown with the ones above: db-Migrate.salam
MigrationCount
func MigrationCount(m: Migrator): intThe example for this item is shown with the ones above: db-Migrate.salam
SplitStatements
func SplitStatements(sql: str): Vector<str>; inside a string is not a separator.The example for this item is shown with the ones above: db-Migrate.salam
EnsureTable
func EnsureTable(m: Migrator, c: dyn Connection): intThe example for this item is shown with the ones above: db-Migrate.salam
SchemaVersion
func SchemaVersion(m: Migrator, c: dyn Connection): intThe example for this item is shown with the ones above: db-Migrate.salam
IsApplied
func IsApplied(m: Migrator, c: dyn Connection, version: int): boolThe example for this item is shown with the ones above: db-Migrate.salam
PendingCount
func PendingCount(m: Migrator, c: dyn Connection): intThe example for this item is shown with the ones above: db-Migrate.salam
MigrateUp
func MigrateUp(m: Migrator, c: dyn Connection): intThe example for this item is shown with the ones above: db-Migrate.salam
Rollback
func Rollback(m: Migrator, c: dyn Connection): boolThe example for this item is shown with the ones above: db-Connection.salam
MigrateTo
func MigrateTo(m: Migrator, c: dyn Connection, target: int): intThe example for this item is shown with the ones above: db-Migrate.salam