mirror of
https://github.com/launchbadge/sqlx.git
synced 2026-03-25 11:30:23 +00:00
feat: introduce migrate.create-schemas
This commit is contained in:
@@ -15,6 +15,7 @@ use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
|
||||
pub(crate) use sqlx_core::migrate::*;
|
||||
use sqlx_core::query_scalar::query_scalar;
|
||||
|
||||
impl MigrateDatabase for Sqlite {
|
||||
fn create_database(url: &str) -> BoxFuture<'_, Result<(), Error>> {
|
||||
@@ -64,10 +65,35 @@ impl MigrateDatabase for Sqlite {
|
||||
}
|
||||
|
||||
impl Migrate for SqliteConnection {
|
||||
fn ensure_migrations_table<'e>(&'e mut self, table_name: &'e str) -> BoxFuture<'e, Result<(), MigrateError>> {
|
||||
fn create_schema_if_not_exists<'e>(
|
||||
&'e mut self,
|
||||
schema_name: &'e str,
|
||||
) -> BoxFuture<'e, Result<(), MigrateError>> {
|
||||
Box::pin(async move {
|
||||
// Check if the schema already exists; if so, don't error.
|
||||
let schema_version: Option<i64> =
|
||||
query_scalar(&format!("PRAGMA {schema_name}.schema_version"))
|
||||
.fetch_optional(&mut *self)
|
||||
.await?;
|
||||
|
||||
if schema_version.is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err(MigrateError::CreateSchemasNotSupported(
|
||||
format!("cannot create new schema {schema_name}; creation of additional schemas in SQLite requires attaching extra database files"),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
fn ensure_migrations_table<'e>(
|
||||
&'e mut self,
|
||||
table_name: &'e str,
|
||||
) -> BoxFuture<'e, Result<(), MigrateError>> {
|
||||
Box::pin(async move {
|
||||
// language=SQLite
|
||||
self.execute(&*format!(r#"
|
||||
self.execute(&*format!(
|
||||
r#"
|
||||
CREATE TABLE IF NOT EXISTS {table_name} (
|
||||
version BIGINT PRIMARY KEY,
|
||||
description TEXT NOT NULL,
|
||||
@@ -76,20 +102,23 @@ CREATE TABLE IF NOT EXISTS {table_name} (
|
||||
checksum BLOB NOT NULL,
|
||||
execution_time BIGINT NOT NULL
|
||||
);
|
||||
"#),
|
||||
)
|
||||
.await?;
|
||||
"#
|
||||
))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn dirty_version<'e>(&'e mut self, table_name: &'e str) -> BoxFuture<'e, Result<Option<i64>, MigrateError>> {
|
||||
fn dirty_version<'e>(
|
||||
&'e mut self,
|
||||
table_name: &'e str,
|
||||
) -> BoxFuture<'e, Result<Option<i64>, MigrateError>> {
|
||||
Box::pin(async move {
|
||||
// language=SQLite
|
||||
let row: Option<(i64,)> = query_as(
|
||||
&format!("SELECT version FROM {table_name} WHERE success = false ORDER BY version LIMIT 1"),
|
||||
)
|
||||
let row: Option<(i64,)> = query_as(&format!(
|
||||
"SELECT version FROM {table_name} WHERE success = false ORDER BY version LIMIT 1"
|
||||
))
|
||||
.fetch_optional(self)
|
||||
.await?;
|
||||
|
||||
@@ -97,13 +126,17 @@ CREATE TABLE IF NOT EXISTS {table_name} (
|
||||
})
|
||||
}
|
||||
|
||||
fn list_applied_migrations<'e>(&'e mut self, table_name: &'e str) -> BoxFuture<'e, Result<Vec<AppliedMigration>, MigrateError>> {
|
||||
fn list_applied_migrations<'e>(
|
||||
&'e mut self,
|
||||
table_name: &'e str,
|
||||
) -> BoxFuture<'e, Result<Vec<AppliedMigration>, MigrateError>> {
|
||||
Box::pin(async move {
|
||||
// language=SQLite
|
||||
let rows: Vec<(i64, Vec<u8>)> =
|
||||
query_as(&format!("SELECT version, checksum FROM {table_name} ORDER BY version"))
|
||||
.fetch_all(self)
|
||||
.await?;
|
||||
let rows: Vec<(i64, Vec<u8>)> = query_as(&format!(
|
||||
"SELECT version, checksum FROM {table_name} ORDER BY version"
|
||||
))
|
||||
.fetch_all(self)
|
||||
.await?;
|
||||
|
||||
let migrations = rows
|
||||
.into_iter()
|
||||
@@ -145,12 +178,12 @@ CREATE TABLE IF NOT EXISTS {table_name} (
|
||||
.map_err(|e| MigrateError::ExecuteMigration(e, migration.version))?;
|
||||
|
||||
// language=SQL
|
||||
let _ = query(
|
||||
&format!(r#"
|
||||
let _ = query(&format!(
|
||||
r#"
|
||||
INSERT INTO {table_name} ( version, description, success, checksum, execution_time )
|
||||
VALUES ( ?1, ?2, TRUE, ?3, -1 )
|
||||
"#),
|
||||
)
|
||||
"#
|
||||
))
|
||||
.bind(migration.version)
|
||||
.bind(&*migration.description)
|
||||
.bind(&*migration.checksum)
|
||||
@@ -167,13 +200,13 @@ CREATE TABLE IF NOT EXISTS {table_name} (
|
||||
|
||||
// language=SQL
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
let _ = query(
|
||||
&format!(r#"
|
||||
let _ = query(&format!(
|
||||
r#"
|
||||
UPDATE {table_name}
|
||||
SET execution_time = ?1
|
||||
WHERE version = ?2
|
||||
"#),
|
||||
)
|
||||
"#
|
||||
))
|
||||
.bind(elapsed.as_nanos() as i64)
|
||||
.bind(migration.version)
|
||||
.execute(self)
|
||||
|
||||
Reference in New Issue
Block a user