use crate::{Backend, Migration};
use arrayvec::ArrayString;
use core::{concat, fmt::Write};
macro_rules! oapth_migration_columns {
() => {
"_oapth_migration_omg_version INT NOT NULL, \
checksum VARCHAR(20) NOT NULL, \
name VARCHAR(128) NOT NULL, \
version INT NOT NULL, \
CONSTRAINT _oapth_migration_unq UNIQUE (version, _oapth_migration_omg_version)"
};
}
macro_rules! oapth_migration_group_columns {
() => {
"version INT NOT NULL PRIMARY KEY, \
name VARCHAR(128) NOT NULL"
};
}
macro_rules! serial_id {
() => {
"id SERIAL NOT NULL PRIMARY KEY,"
};
}
pub const _CREATE_MIGRATION_TABLES_MSSQL: &str = concat!(
"IF (NOT EXISTS (SELECT 1 FROM sys.schemas WHERE name = '_oapth'))
BEGIN
EXEC ('CREATE SCHEMA [_oapth]')
END
IF (NOT EXISTS (
SELECT
1
FROM
information_schema.tables
WHERE
table_name = '_oapth_migration_group' AND table_schema = '_oapth'
))
BEGIN
CREATE TABLE _oapth._oapth_migration_group (",
oapth_migration_group_columns!(),
");
END
IF (NOT EXISTS (
SELECT
1
FROM
information_schema.tables
WHERE
table_name = '_oapth_migration' AND table_schema = '_oapth'
))
BEGIN
CREATE TABLE _oapth._oapth_migration (
id INT NOT NULL IDENTITY PRIMARY KEY,
created_on VARCHAR(32) NOT NULL DEFAULT CONVERT(VARCHAR(32), CURRENT_TIMESTAMP, 120),",
oapth_migration_columns!(),
");
END"
);
pub const _CREATE_MIGRATION_TABLES_MYSQL: &str = concat!(
"CREATE TABLE IF NOT EXISTS _oapth_migration_group (",
oapth_migration_group_columns!(),
"); \
CREATE TABLE IF NOT EXISTS _oapth_migration (",
serial_id!(),
"created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,",
oapth_migration_columns!(),
");"
);
pub const _CREATE_MIGRATION_TABLES_POSTGRESQL: &str = concat!(
"CREATE SCHEMA IF NOT EXISTS _oapth; \
CREATE TABLE IF NOT EXISTS _oapth._oapth_migration_group (",
oapth_migration_group_columns!(),
");
CREATE TABLE IF NOT EXISTS _oapth._oapth_migration (",
serial_id!(),
"created_on TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,",
oapth_migration_columns!(),
");"
);
pub const _CREATE_MIGRATION_TABLES_SQLITE: &str = concat!(
"CREATE TABLE IF NOT EXISTS _oapth_migration_group (",
oapth_migration_group_columns!(),
"); \
CREATE TABLE IF NOT EXISTS _oapth_migration (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,",
oapth_migration_columns!(),
");"
);
#[inline]
pub async fn _delete_migrations<B>(
backend: &mut B,
mg: &crate::MigrationGroup,
schema: &str,
version: i32,
) -> crate::Result<()>
where
B: Backend,
{
let mut buffer = ArrayString::<[u8; 128]>::new();
buffer.write_fmt(format_args!(
"DELETE FROM {schema}_oapth_migration WHERE _oapth_migration_omg_version = {mg_version} AND version > {m_version}",
m_version = version,
mg_version = mg.version(),
schema = schema,
))?;
backend.execute(&buffer).await?;
Ok(())
}
#[inline]
pub async fn _insert_migrations<'a, B, I>(
backend: &'a mut B,
mg: &'a crate::MigrationGroup,
schema: &str,
migrations: I,
) -> crate::Result<()>
where
B: Backend,
I: Clone + Iterator<Item = &'a Migration> + 'a,
{
let mut insert_migration_group_str = ArrayString::<[u8; 512]>::new();
insert_migration_group_str.write_fmt(format_args!(
"INSERT INTO {schema}_oapth_migration_group (version, name)
SELECT * FROM (SELECT {mg_version} AS version, '{mg_name}' AS name) AS tmp
WHERE NOT EXISTS (
SELECT 1 FROM {schema}_oapth_migration_group WHERE version = {mg_version}
);",
mg_name = mg.name(),
mg_version = mg.version(),
schema = schema
))?;
backend.execute(&insert_migration_group_str).await?;
backend.transaction(migrations.clone().map(|m| m.sql_up())).await?;
backend
.transaction(
migrations.filter_map(|m| _insert_oapth_migration_str(mg.version(), &m.common, schema).ok()),
)
.await?;
Ok(())
}
#[inline]
pub fn _migrations_by_mg_version_query(
mg_version: i32,
schema: &str,
) -> crate::Result<ArrayString<[u8; 512]>> {
let mut s = ArrayString::new();
s.write_fmt(format_args!(
"SELECT \
_oapth_migration.version, \
_oapth_migration_group.version as omg_version, \
_oapth_migration_group.name as omg_name, \
_oapth_migration.checksum, \
_oapth_migration.created_on, \
_oapth_migration.name \
FROM \
{schema}_oapth_migration_group \
JOIN \
{schema}_oapth_migration ON _oapth_migration._oapth_migration_omg_version = _oapth_migration_group.version \
WHERE \
_oapth_migration_group.version = {mg_version} \
ORDER BY \
_oapth_migration.version ASC;",
mg_version = mg_version,
schema = schema
))?;
Ok(s)
}
#[inline]
fn _insert_oapth_migration_str(
mg_version: i32,
m: &crate::MigrationCommon,
schema: &str,
) -> crate::Result<ArrayString<[u8; 512]>> {
let mut buffer = ArrayString::<[u8; 512]>::new();
buffer.write_fmt(format_args!(
"INSERT INTO {schema}_oapth_migration (
version, _oapth_migration_omg_version, checksum, name
) VALUES (
{m_version}, {mg_version}, '{m_checksum}', '{m_name}'
);",
m_checksum = m.checksum,
m_name = m.name,
m_version = m.version,
mg_version = mg_version,
schema = schema,
))?;
Ok(buffer)
}