mirror of
https://github.com/lldap/lldap.git
synced 2026-07-25 17:58:44 +00:00
server: Fix schema migration from v8 for sqlite and postgres
Neither supports limits, but we can delete all the duplicate memberships and re-insert a single one
This commit is contained in:
committed by
nitnelave
parent
64514ddfc6
commit
0ddeab8caa
@@ -5,8 +5,8 @@ use crate::domain::{
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
sea_query::{
|
sea_query::{
|
||||||
self, all, Alias, BinOper, BlobSize::Blob, ColumnDef, Expr, ForeignKey, ForeignKeyAction,
|
self, all, BinOper, BlobSize::Blob, ColumnDef, Expr, ForeignKey, ForeignKeyAction, Func,
|
||||||
Func, Index, Query, SimpleExpr, Table, Value,
|
Index, Query, SimpleExpr, Table, Value,
|
||||||
},
|
},
|
||||||
ConnectionTrait, DatabaseTransaction, DbErr, DeriveIden, FromQueryResult, Iden, Order,
|
ConnectionTrait, DatabaseTransaction, DbErr, DeriveIden, FromQueryResult, Iden, Order,
|
||||||
Statement, TransactionTrait,
|
Statement, TransactionTrait,
|
||||||
@@ -970,21 +970,15 @@ async fn migrate_to_v8(transaction: DatabaseTransaction) -> Result<DatabaseTrans
|
|||||||
let builder = transaction.get_database_backend();
|
let builder = transaction.get_database_backend();
|
||||||
// Remove duplicate memberships.
|
// Remove duplicate memberships.
|
||||||
#[derive(FromQueryResult)]
|
#[derive(FromQueryResult)]
|
||||||
#[allow(dead_code)]
|
|
||||||
struct MembershipInfo {
|
struct MembershipInfo {
|
||||||
user_id: UserId,
|
user_id: UserId,
|
||||||
group_id: GroupId,
|
group_id: GroupId,
|
||||||
cnt: i64,
|
|
||||||
}
|
}
|
||||||
let mut delete_queries = MembershipInfo::find_by_statement(
|
for MembershipInfo { user_id, group_id } in MembershipInfo::find_by_statement(
|
||||||
builder.build(
|
builder.build(
|
||||||
Query::select()
|
Query::select()
|
||||||
.from(Memberships::Table)
|
.from(Memberships::Table)
|
||||||
.columns([Memberships::UserId, Memberships::GroupId])
|
.columns([Memberships::UserId, Memberships::GroupId])
|
||||||
.expr_as(
|
|
||||||
Expr::count(Expr::col((Memberships::Table, Memberships::UserId))),
|
|
||||||
Alias::new("cnt"),
|
|
||||||
)
|
|
||||||
.group_by_columns([Memberships::UserId, Memberships::GroupId])
|
.group_by_columns([Memberships::UserId, Memberships::GroupId])
|
||||||
.cond_having(all![SimpleExpr::Binary(
|
.cond_having(all![SimpleExpr::Binary(
|
||||||
Box::new(Expr::col((Memberships::Table, Memberships::UserId)).count()),
|
Box::new(Expr::col((Memberships::Table, Memberships::UserId)).count()),
|
||||||
@@ -996,38 +990,29 @@ async fn migrate_to_v8(transaction: DatabaseTransaction) -> Result<DatabaseTrans
|
|||||||
.all(&transaction)
|
.all(&transaction)
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(
|
{
|
||||||
|MembershipInfo {
|
transaction
|
||||||
user_id,
|
.execute(
|
||||||
group_id,
|
builder.build(
|
||||||
cnt,
|
|
||||||
}| {
|
|
||||||
builder
|
|
||||||
.build(
|
|
||||||
Query::delete()
|
Query::delete()
|
||||||
.from_table(Memberships::Table)
|
.from_table(Memberships::Table)
|
||||||
.cond_where(all![
|
.cond_where(all![
|
||||||
Expr::col(Memberships::UserId).eq(user_id),
|
Expr::col(Memberships::UserId).eq(&user_id),
|
||||||
Expr::col(Memberships::GroupId).eq(group_id)
|
Expr::col(Memberships::GroupId).eq(group_id)
|
||||||
])
|
]),
|
||||||
.limit(cnt as u64 - 1),
|
),
|
||||||
)
|
)
|
||||||
.to_owned()
|
.await?;
|
||||||
},
|
transaction
|
||||||
)
|
.execute(
|
||||||
.peekable();
|
builder.build(
|
||||||
if delete_queries.peek().is_some() {
|
Query::insert()
|
||||||
match transaction.get_database_backend() {
|
.into_table(Memberships::Table)
|
||||||
sea_orm::DatabaseBackend::Sqlite => {
|
.columns([Memberships::UserId, Memberships::GroupId])
|
||||||
return Err(DbErr::Migration(format!(
|
.values_panic([user_id.into(), group_id.into()]),
|
||||||
"The Sqlite driver does not support LIMIT in DELETE. Run these queries manually:\n{}" , delete_queries.map(|s| s.to_string()).join("\n"))));
|
),
|
||||||
}
|
)
|
||||||
sea_orm::DatabaseBackend::MySql | sea_orm::DatabaseBackend::Postgres => {
|
.await?;
|
||||||
for query in delete_queries {
|
|
||||||
transaction.execute(query).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
transaction
|
transaction
|
||||||
.execute(
|
.execute(
|
||||||
|
|||||||
Reference in New Issue
Block a user