2020-01-03 08:07:05 -06:00
// Copyright 2017-2018 New Vector Ltd
// Copyright 2019-2020 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,
2020-05-28 05:15:21 -05:00
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implie
2020-01-03 08:07:05 -06:00
// See the License for the specific language governing permissions and
// limitations under the License.
package postgres
import (
2022-09-09 07:14:52 -05:00
"context"
2020-01-03 08:07:05 -06:00
"database/sql"
2022-09-09 07:14:52 -05:00
"errors"
2021-04-26 07:25:57 -05:00
"fmt"
2020-03-17 10:12:01 -05:00
2020-11-05 04:19:23 -06:00
// Import the postgres database driver.
_ "github.com/lib/pq"
2023-10-27 10:36:40 -05:00
"github.com/matrix-org/dendrite/roomserver/types"
2022-08-08 03:18:57 -05:00
2020-08-25 06:32:29 -05:00
"github.com/matrix-org/dendrite/internal/caching"
2020-04-16 04:06:55 -05:00
"github.com/matrix-org/dendrite/internal/sqlutil"
2020-11-05 04:19:23 -06:00
"github.com/matrix-org/dendrite/roomserver/storage/postgres/deltas"
2020-05-26 09:42:42 -05:00
"github.com/matrix-org/dendrite/roomserver/storage/shared"
2020-12-02 11:41:00 -06:00
"github.com/matrix-org/dendrite/setup/config"
2020-01-03 08:07:05 -06:00
)
// A Database is used to store room events and stream offsets.
type Database struct {
2020-05-26 09:42:42 -05:00
shared . Database
2020-01-03 08:07:05 -06:00
}
2023-10-27 10:36:40 -05:00
func ( d * Database ) GetAllStateSnapshots ( ctx context . Context , roomNID types . RoomNID ) ( [ ] types . StateSnapshotNID , error ) {
return d . StateSnapshotTable . GetAllStateSnapshots ( ctx , nil , roomNID )
}
2020-01-03 08:07:05 -06:00
// Open a postgres database.
2023-07-19 06:37:04 -05:00
func Open ( ctx context . Context , conMan * sqlutil . Connections , dbProperties * config . DatabaseOptions , cache caching . RoomServerCaches ) ( * Database , error ) {
2020-01-03 08:07:05 -06:00
var d Database
var err error
2023-03-17 06:09:45 -05:00
db , writer , err := conMan . Connection ( dbProperties )
2022-05-03 10:35:06 -05:00
if err != nil {
2021-04-26 07:25:57 -05:00
return nil , fmt . Errorf ( "sqlutil.Open: %w" , err )
2020-01-03 08:07:05 -06:00
}
2020-11-05 04:19:23 -06:00
2021-04-26 07:25:57 -05:00
// Create the tables.
2022-07-25 04:39:22 -05:00
if err = d . create ( db ) ; err != nil {
2020-11-05 04:19:23 -06:00
return nil , err
}
2021-04-26 07:25:57 -05:00
2022-07-25 04:39:22 -05:00
// Special case, since this migration uses several tables, so it needs to
// be sure that all tables are created first.
2023-03-17 06:09:45 -05:00
if err = executeMigration ( ctx , db ) ; err != nil {
2022-09-09 07:14:52 -05:00
return nil , err
2020-11-05 04:19:23 -06:00
}
2021-04-26 07:25:57 -05:00
// Then prepare the statements. Now that the migrations have run, any columns referred
// to in the database code should now exist.
2022-08-08 03:18:57 -05:00
if err = d . prepare ( db , writer , cache ) ; err != nil {
2020-11-05 04:19:23 -06:00
return nil , err
}
return & d , nil
}
2022-09-09 07:14:52 -05:00
func executeMigration ( ctx context . Context , db * sql . DB ) error {
// TODO: Remove when we are sure we are not having goose artefacts in the db
// This forces an error, which indicates the migration is already applied, since the
// column event_nid was removed from the table
migrationName := "roomserver: state blocks refactor"
var cName string
err := db . QueryRowContext ( ctx , "select column_name from information_schema.columns where table_name = 'roomserver_state_block' AND column_name = 'event_nid'" ) . Scan ( & cName )
if err != nil {
if errors . Is ( err , sql . ErrNoRows ) { // migration was already executed, as the column was removed
if err = sqlutil . InsertMigration ( ctx , db , migrationName ) ; err != nil {
2022-09-13 01:07:43 -05:00
return fmt . Errorf ( "unable to manually insert migration '%s': %w" , migrationName , err )
2022-09-09 07:14:52 -05:00
}
return nil
}
return err
}
m := sqlutil . NewMigrator ( db )
m . AddMigrations ( sqlutil . Migration {
Version : migrationName ,
Up : deltas . UpStateBlocksRefactor ,
} )
return m . Up ( ctx )
}
2021-04-26 07:25:57 -05:00
func ( d * Database ) create ( db * sql . DB ) error {
2022-05-09 08:30:32 -05:00
if err := CreateEventStateKeysTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-09 08:30:32 -05:00
if err := CreateEventTypesTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-09 08:30:32 -05:00
if err := CreateEventJSONTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-09 08:30:32 -05:00
if err := CreateEventsTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-16 12:33:16 -05:00
if err := CreateRoomsTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-16 12:33:16 -05:00
if err := CreateStateBlockTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-16 12:33:16 -05:00
if err := CreateStateSnapshotTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-10 07:41:12 -05:00
if err := CreatePrevEventsTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-16 12:33:16 -05:00
if err := CreateRoomAliasesTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-10 07:41:12 -05:00
if err := CreateInvitesTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-10 07:41:12 -05:00
if err := CreateMembershipTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-10 07:41:12 -05:00
if err := CreatePublishedTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2022-05-10 07:41:12 -05:00
if err := CreateRedactionsTable ( db ) ; err != nil {
2021-04-26 07:25:57 -05:00
return err
}
2023-06-12 05:45:42 -05:00
if err := CreateUserRoomKeysTable ( db ) ; err != nil {
return err
}
2021-04-26 07:25:57 -05:00
return nil
}
2022-05-03 10:35:06 -05:00
func ( d * Database ) prepare ( db * sql . DB , writer sqlutil . Writer , cache caching . RoomServerCaches ) error {
2022-05-09 08:30:32 -05:00
eventStateKeys , err := PrepareEventStateKeysTable ( db )
2020-05-26 09:42:42 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-26 09:42:42 -05:00
}
2022-05-09 08:30:32 -05:00
eventTypes , err := PrepareEventTypesTable ( db )
2020-05-26 09:42:42 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-26 09:42:42 -05:00
}
2022-05-09 08:30:32 -05:00
eventJSON , err := PrepareEventJSONTable ( db )
2020-05-26 10:45:28 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-26 10:45:28 -05:00
}
2022-05-09 08:30:32 -05:00
events , err := PrepareEventsTable ( db )
2020-05-26 10:45:28 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-26 10:45:28 -05:00
}
2022-05-16 12:33:16 -05:00
rooms , err := PrepareRoomsTable ( db )
2020-05-26 12:23:39 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-26 12:23:39 -05:00
}
2022-05-16 12:33:16 -05:00
stateBlock , err := PrepareStateBlockTable ( db )
2020-05-27 03:36:09 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-27 03:36:09 -05:00
}
2022-05-16 12:33:16 -05:00
stateSnapshot , err := PrepareStateSnapshotTable ( db )
2020-05-27 03:36:09 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-27 03:36:09 -05:00
}
2022-05-10 07:41:12 -05:00
prevEvents , err := PreparePrevEventsTable ( db )
2020-05-27 03:36:09 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-27 03:36:09 -05:00
}
2022-05-16 12:33:16 -05:00
roomAliases , err := PrepareRoomAliasesTable ( db )
2020-05-27 03:36:09 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-27 03:36:09 -05:00
}
2022-05-10 07:41:12 -05:00
invites , err := PrepareInvitesTable ( db )
2020-05-27 05:03:47 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-27 05:03:47 -05:00
}
2022-05-10 07:41:12 -05:00
membership , err := PrepareMembershipTable ( db )
2020-05-27 05:03:47 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-05-27 05:03:47 -05:00
}
2022-05-10 07:41:12 -05:00
published , err := PreparePublishedTable ( db )
2020-07-02 09:41:18 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-07-02 09:41:18 -05:00
}
2022-05-10 07:41:12 -05:00
redactions , err := PrepareRedactionsTable ( db )
2020-07-06 11:49:15 -05:00
if err != nil {
2020-11-05 04:19:23 -06:00
return err
2020-07-06 11:49:15 -05:00
}
2023-01-19 14:02:32 -06:00
purge , err := PreparePurgeStatements ( db )
if err != nil {
return err
}
2023-06-12 05:45:42 -05:00
userRoomKeys , err := PrepareUserRoomKeysTable ( db )
if err != nil {
return err
}
2020-05-26 09:42:42 -05:00
d . Database = shared . Database {
2023-03-01 10:06:47 -06:00
DB : db ,
EventDatabase : shared . EventDatabase {
DB : db ,
Cache : cache ,
Writer : writer ,
EventsTable : events ,
EventJSONTable : eventJSON ,
EventTypesTable : eventTypes ,
EventStateKeysTable : eventStateKeys ,
PrevEventsTable : prevEvents ,
RedactionsTable : redactions ,
} ,
Cache : cache ,
Writer : writer ,
RoomsTable : rooms ,
StateBlockTable : stateBlock ,
StateSnapshotTable : stateSnapshot ,
RoomAliasesTable : roomAliases ,
InvitesTable : invites ,
MembershipTable : membership ,
PublishedTable : published ,
Purge : purge ,
2023-06-12 05:45:42 -05:00
UserRoomKeyTable : userRoomKeys ,
2020-05-26 09:42:42 -05:00
}
2020-11-05 04:19:23 -06:00
return nil
2020-01-03 08:07:05 -06:00
}