2023-01-19 14:02:32 -06:00
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sqlite3
import (
"context"
"database/sql"
"github.com/matrix-org/dendrite/internal/sqlutil"
"github.com/matrix-org/dendrite/roomserver/types"
)
const purgeEventJSONSQL = "" +
"DELETE FROM roomserver_event_json WHERE event_nid IN (" +
" SELECT event_nid FROM roomserver_events WHERE room_nid = $1" +
")"
const purgeEventsSQL = "" +
"DELETE FROM roomserver_events WHERE room_nid = $1"
const purgeInvitesSQL = "" +
"DELETE FROM roomserver_invites WHERE room_nid = $1"
const purgeMembershipsSQL = "" +
"DELETE FROM roomserver_membership WHERE room_nid = $1"
const purgePreviousEventsSQL = "" +
"DELETE FROM roomserver_previous_events WHERE event_nids IN(" +
" SELECT event_nid FROM roomserver_events WHERE room_nid = $1" +
")"
2024-09-10 13:43:50 -05:00
// This removes the majority of prev events and is way faster than the above.
// The above query is still needed to delete the remaining prev events.
const purgePreviousEvents2SQL = "" +
"DELETE FROM roomserver_previous_events AS rpe WHERE EXISTS(SELECT event_id FROM roomserver_events AS re WHERE room_nid = $1 AND re.event_id = rpe.previous_event_id)"
2023-01-19 14:02:32 -06:00
const purgePublishedSQL = "" +
"DELETE FROM roomserver_published WHERE room_id = $1"
const purgeRedactionsSQL = "" +
"DELETE FROM roomserver_redactions WHERE redaction_event_id IN(" +
" SELECT event_id FROM roomserver_events WHERE room_nid = $1" +
")"
const purgeRoomAliasesSQL = "" +
"DELETE FROM roomserver_room_aliases WHERE room_id = $1"
const purgeRoomSQL = "" +
"DELETE FROM roomserver_rooms WHERE room_nid = $1"
const purgeStateSnapshotEntriesSQL = "" +
"DELETE FROM roomserver_state_snapshots WHERE room_nid = $1"
type purgeStatements struct {
purgeEventJSONStmt * sql . Stmt
purgeEventsStmt * sql . Stmt
purgeInvitesStmt * sql . Stmt
purgeMembershipsStmt * sql . Stmt
purgePreviousEventsStmt * sql . Stmt
2024-09-10 13:43:50 -05:00
purgePreviousEvents2Stmt * sql . Stmt
2023-01-19 14:02:32 -06:00
purgePublishedStmt * sql . Stmt
purgeRedactionStmt * sql . Stmt
purgeRoomAliasesStmt * sql . Stmt
purgeRoomStmt * sql . Stmt
purgeStateSnapshotEntriesStmt * sql . Stmt
stateSnapshot * stateSnapshotStatements
}
func PreparePurgeStatements ( db * sql . DB , stateSnapshot * stateSnapshotStatements ) ( * purgeStatements , error ) {
s := & purgeStatements { stateSnapshot : stateSnapshot }
return s , sqlutil . StatementList {
{ & s . purgeEventJSONStmt , purgeEventJSONSQL } ,
{ & s . purgeEventsStmt , purgeEventsSQL } ,
{ & s . purgeInvitesStmt , purgeInvitesSQL } ,
{ & s . purgeMembershipsStmt , purgeMembershipsSQL } ,
{ & s . purgePublishedStmt , purgePublishedSQL } ,
{ & s . purgePreviousEventsStmt , purgePreviousEventsSQL } ,
2024-09-10 13:43:50 -05:00
{ & s . purgePreviousEvents2Stmt , purgePreviousEvents2SQL } ,
2023-01-19 14:02:32 -06:00
{ & s . purgeRedactionStmt , purgeRedactionsSQL } ,
{ & s . purgeRoomAliasesStmt , purgeRoomAliasesSQL } ,
{ & s . purgeRoomStmt , purgeRoomSQL } ,
//{&s.purgeStateBlockEntriesStmt, purgeStateBlockEntriesSQL},
{ & s . purgeStateSnapshotEntriesStmt , purgeStateSnapshotEntriesSQL } ,
} . Prepare ( db )
}
func ( s * purgeStatements ) PurgeRoom (
ctx context . Context , txn * sql . Tx , roomNID types . RoomNID , roomID string ,
) error {
// purge by roomID
purgeByRoomID := [ ] * sql . Stmt {
s . purgeRoomAliasesStmt ,
s . purgePublishedStmt ,
}
for _ , stmt := range purgeByRoomID {
_ , err := sqlutil . TxStmt ( txn , stmt ) . ExecContext ( ctx , roomID )
if err != nil {
return err
}
}
// purge by roomNID
if err := s . purgeStateBlocks ( ctx , txn , roomNID ) ; err != nil {
return err
}
purgeByRoomNID := [ ] * sql . Stmt {
s . purgeStateSnapshotEntriesStmt ,
s . purgeInvitesStmt ,
s . purgeMembershipsStmt ,
2024-09-10 13:43:50 -05:00
s . purgePreviousEvents2Stmt , // Fast purge the majority of events
s . purgePreviousEventsStmt , // Slow purge the remaining events
2023-01-19 14:02:32 -06:00
s . purgeEventJSONStmt ,
s . purgeRedactionStmt ,
s . purgeEventsStmt ,
s . purgeRoomStmt ,
}
for _ , stmt := range purgeByRoomNID {
_ , err := sqlutil . TxStmt ( txn , stmt ) . ExecContext ( ctx , roomNID )
if err != nil {
return err
}
}
return nil
}
func ( s * purgeStatements ) purgeStateBlocks (
ctx context . Context , txn * sql . Tx , roomNID types . RoomNID ,
) error {
// Get all stateBlockNIDs
stateBlockNIDs , err := s . stateSnapshot . selectStateBlockNIDsForRoomNID ( ctx , txn , roomNID )
if err != nil {
return err
}
params := make ( [ ] interface { } , len ( stateBlockNIDs ) )
seenNIDs := make ( map [ types . StateBlockNID ] struct { } , len ( stateBlockNIDs ) )
// dedupe NIDs
for k , v := range stateBlockNIDs {
if _ , ok := seenNIDs [ v ] ; ok {
continue
}
params [ k ] = v
seenNIDs [ v ] = struct { } { }
}
query := "DELETE FROM roomserver_state_block WHERE state_block_nid IN($1)"
return sqlutil . RunLimitedVariablesExec ( ctx , query , txn , params , sqlutil . SQLite3MaxVariables )
}