Skip to main content

Database

Enum Database 

Source
pub enum Database {
    Sqlite(Pool<Sqlite>),
    Postgres(Pool<Postgres>),
}
Expand description

The connection pool, and the only way to reach it.

The pool is private to this crate: everything else goes through a table module, Database::transaction or Database::pool_stats. That is what keeps SQL — and the dialect it is written in — in one crate.

Variants§

§

Sqlite(Pool<Sqlite>)

§

Postgres(Pool<Postgres>)

Implementations§

Source§

impl Database

Source

pub fn dialect(&self) -> Dialect

Which dialect this database speaks.

Source

pub fn exec(&self) -> Exec<'_>

This database as a target for one statement.

Source

pub async fn transaction(&self) -> Result<Tx, Error>

Begins a transaction.

Source

pub async fn write_transaction(&self) -> Result<Tx, Error>

Begins a transaction that holds the write lock from its first statement (BEGIN IMMEDIATE), for one that reads and then writes on what it read while another process may be writing.

A plain transaction is deferred: it takes a read snapshot at its first SELECT and asks for the write lock only at its first write. In WAL mode, if another connection committed in between, that upgrade fails at once with SQLITE_BUSY_SNAPSHOT — busy_timeout cannot help, since waiting would not make the snapshot current. Taking the lock up front makes the transaction wait its turn under busy_timeout instead, and then read what it writes against.

Source

pub fn pool_stats(&self) -> PoolStats

The pool’s size and idle count, read now rather than tracked.

Source

pub async fn close(&self)

Closes the pool: every later query fails with PoolClosed.

Waits for checked-out connections to be returned. Also how a test simulates the database going away underneath a running server.

Source

pub async fn open(url: &str) -> Result<Database, Error>

Opens the database at url, whose scheme picks the backend. Does not migrate.

sqlite: creates the file if it is not there yet, and pins the two pragmas the schema depends on. postgres:/postgresql: expects the database to exist — creating one is a privileged act an operator performs, not something a server does to a cluster it was pointed at. Any other scheme is refused by name here, rather than as a driver error several frames down.

Applying the schema is a separate, named act: migrate, acme-proxy migrate, or the worker role at startup. It used to happen here, which meant every subcommand — audit list, completions, a health check — silently upgraded the schema of whatever database it was pointed at, and two processes starting together raced MIGRATOR::run with no lock between them (SQLite gives sqlx none; PostgreSQL does, an advisory lock, so there the one-owner rule is belt and braces).

A caller that needs the schema present asks pending_migrations and refuses by name, or uses connect_and_migrate.

Source

pub async fn connect_and_migrate(url: &str) -> Result<Database, Error>

open followed by migrate.

For the two callers that own the schema — acme-proxy migrate and acme-proxy init — and for tests over a file-backed database, which want the same thing in one step.

Source

pub async fn migrate(&self) -> Result<(), Error>

Applies every embedded migration that has not run yet.

Idempotent: sqlx tracks each file by version and checksum, so running this against an up-to-date database does nothing.

Source

pub async fn pending_migrations(&self) -> Result<Vec<i64>, Error>

The versions of the embedded migrations this database has not applied.

Empty means the schema is current. What the roles that must not migrate check before serving, so an unmigrated database stops them by name rather than failing later as a missing table.

A database with no _sqlx_migrations table has applied nothing — that is a freshly created file, not an error.

Source

pub async fn connect_in_memory() -> Result<Database, Error>

Builds a throwaway in-memory database with migrations applied. Pinned to a single connection so the whole test shares one in-memory database (each SQLite connection otherwise gets its own).

Source§

impl Database

Source

pub async fn transfer_to( &self, target: &Database, ) -> Result<TransferReport, Error>

Copies every row of this database into target.

The whole copy is one transaction on the target, so a failure anywhere leaves it exactly as it was rather than half-populated. The source is only read.

The caller is responsible for the two things this cannot check: that target’s schema is current (ask Database::pending_migrations) and that nothing is writing to the source. See the module doc.

Trait Implementations§

Source§

impl<'a> From<&'a Database> for Exec<'a>

Source§

fn from(database: &'a Database) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more