Add prefixes to namespace the SQL tables. (#177)

* Add prefixes to namespace the SQL tables.

This means that multiple components can share a single database schema
without colliding with each other.

Once this lands it will be possible to run a single monolithic dendrite
against a single postgresql schema.

Hopefully this will make trivial deployments and development easier.

* Comment
This commit is contained in:
Mark Haines 2017-08-07 11:51:46 +01:00 committed by GitHub
parent 21a8c24d5f
commit 4d1504ee93
25 changed files with 183 additions and 160 deletions

View file

@ -25,7 +25,7 @@ import (
const accountsSchema = ` const accountsSchema = `
-- Stores data about accounts. -- Stores data about accounts.
CREATE TABLE IF NOT EXISTS accounts ( CREATE TABLE IF NOT EXISTS account_accounts (
-- The Matrix user ID localpart for this account -- The Matrix user ID localpart for this account
localpart TEXT NOT NULL PRIMARY KEY, localpart TEXT NOT NULL PRIMARY KEY,
-- When this account was first created, as a unix timestamp (ms resolution). -- When this account was first created, as a unix timestamp (ms resolution).
@ -38,13 +38,13 @@ CREATE TABLE IF NOT EXISTS accounts (
` `
const insertAccountSQL = "" + const insertAccountSQL = "" +
"INSERT INTO accounts(localpart, created_ts, password_hash) VALUES ($1, $2, $3)" "INSERT INTO account_accounts(localpart, created_ts, password_hash) VALUES ($1, $2, $3)"
const selectAccountByLocalpartSQL = "" + const selectAccountByLocalpartSQL = "" +
"SELECT localpart FROM accounts WHERE localpart = $1" "SELECT localpart FROM account_accounts WHERE localpart = $1"
const selectPasswordHashSQL = "" + const selectPasswordHashSQL = "" +
"SELECT password_hash FROM accounts WHERE localpart = $1" "SELECT password_hash FROM account_accounts WHERE localpart = $1"
// TODO: Update password // TODO: Update password

View file

@ -23,7 +23,7 @@ import (
const membershipSchema = ` const membershipSchema = `
-- Stores data about users memberships to rooms. -- Stores data about users memberships to rooms.
CREATE TABLE IF NOT EXISTS memberships ( CREATE TABLE IF NOT EXISTS account_memberships (
-- The Matrix user ID localpart for the member -- The Matrix user ID localpart for the member
localpart TEXT NOT NULL, localpart TEXT NOT NULL,
-- The room this user is a member of -- The room this user is a member of
@ -36,25 +36,25 @@ CREATE TABLE IF NOT EXISTS memberships (
); );
-- Use index to process deletion by ID more efficiently -- Use index to process deletion by ID more efficiently
CREATE UNIQUE INDEX IF NOT EXISTS membership_event_id ON memberships(event_id); CREATE UNIQUE INDEX IF NOT EXISTS account_membership_event_id ON account_memberships(event_id);
` `
const insertMembershipSQL = ` const insertMembershipSQL = `
INSERT INTO memberships(localpart, room_id, event_id) VALUES ($1, $2, $3) INSERT INTO account_memberships(localpart, room_id, event_id) VALUES ($1, $2, $3)
ON CONFLICT (localpart, room_id) DO UPDATE SET event_id = EXCLUDED.event_id ON CONFLICT (localpart, room_id) DO UPDATE SET event_id = EXCLUDED.event_id
` `
const selectMembershipSQL = "" + const selectMembershipSQL = "" +
"SELECT * from memberships WHERE localpart = $1 AND room_id = $2" "SELECT * from account_memberships WHERE localpart = $1 AND room_id = $2"
const selectMembershipsByLocalpartSQL = "" + const selectMembershipsByLocalpartSQL = "" +
"SELECT room_id, event_id FROM memberships WHERE localpart = $1" "SELECT room_id, event_id FROM account_memberships WHERE localpart = $1"
const deleteMembershipsByEventIDsSQL = "" + const deleteMembershipsByEventIDsSQL = "" +
"DELETE FROM memberships WHERE event_id = ANY($1)" "DELETE FROM account_memberships WHERE event_id = ANY($1)"
const updateMembershipByEventIDSQL = "" + const updateMembershipByEventIDSQL = "" +
"UPDATE memberships SET event_id = $2 WHERE event_id = $1" "UPDATE account_memberships SET event_id = $2 WHERE event_id = $1"
type membershipStatements struct { type membershipStatements struct {
deleteMembershipsByEventIDsStmt *sql.Stmt deleteMembershipsByEventIDsStmt *sql.Stmt

View file

@ -22,7 +22,7 @@ import (
const profilesSchema = ` const profilesSchema = `
-- Stores data about accounts profiles. -- Stores data about accounts profiles.
CREATE TABLE IF NOT EXISTS profiles ( CREATE TABLE IF NOT EXISTS account_profiles (
-- The Matrix user ID localpart for this account -- The Matrix user ID localpart for this account
localpart TEXT NOT NULL PRIMARY KEY, localpart TEXT NOT NULL PRIMARY KEY,
-- The display name for this account -- The display name for this account
@ -33,16 +33,16 @@ CREATE TABLE IF NOT EXISTS profiles (
` `
const insertProfileSQL = "" + const insertProfileSQL = "" +
"INSERT INTO profiles(localpart, display_name, avatar_url) VALUES ($1, $2, $3)" "INSERT INTO account_profiles(localpart, display_name, avatar_url) VALUES ($1, $2, $3)"
const selectProfileByLocalpartSQL = "" + const selectProfileByLocalpartSQL = "" +
"SELECT localpart, display_name, avatar_url FROM profiles WHERE localpart = $1" "SELECT localpart, display_name, avatar_url FROM account_profiles WHERE localpart = $1"
const setAvatarURLSQL = "" + const setAvatarURLSQL = "" +
"UPDATE profiles SET avatar_url = $1 WHERE localpart = $2" "UPDATE account_profiles SET avatar_url = $1 WHERE localpart = $2"
const setDisplayNameSQL = "" + const setDisplayNameSQL = "" +
"UPDATE profiles SET display_name = $1 WHERE localpart = $2" "UPDATE account_profiles SET display_name = $1 WHERE localpart = $2"
type profilesStatements struct { type profilesStatements struct {
insertProfileStmt *sql.Stmt insertProfileStmt *sql.Stmt

View file

@ -44,7 +44,7 @@ func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName)
return nil, err return nil, err
} }
partitions := common.PartitionOffsetStatements{} partitions := common.PartitionOffsetStatements{}
if err = partitions.Prepare(db); err != nil { if err = partitions.Prepare(db, "account"); err != nil {
return nil, err return nil, err
} }
a := accountsStatements{} a := accountsStatements{}

View file

@ -25,7 +25,7 @@ import (
const devicesSchema = ` const devicesSchema = `
-- Stores data about devices. -- Stores data about devices.
CREATE TABLE IF NOT EXISTS devices ( CREATE TABLE IF NOT EXISTS device_devices (
-- The access token granted to this device. This has to be the primary key -- The access token granted to this device. This has to be the primary key
-- so we can distinguish which device is making a given request. -- so we can distinguish which device is making a given request.
access_token TEXT NOT NULL PRIMARY KEY, access_token TEXT NOT NULL PRIMARY KEY,
@ -42,17 +42,17 @@ CREATE TABLE IF NOT EXISTS devices (
); );
-- Device IDs must be unique for a given user. -- Device IDs must be unique for a given user.
CREATE UNIQUE INDEX IF NOT EXISTS localpart_id_idx ON devices(localpart, device_id); CREATE UNIQUE INDEX IF NOT EXISTS device_localpart_id_idx ON device_devices(localpart, device_id);
` `
const insertDeviceSQL = "" + const insertDeviceSQL = "" +
"INSERT INTO devices(device_id, localpart, access_token, created_ts) VALUES ($1, $2, $3, $4)" "INSERT INTO device_devices(device_id, localpart, access_token, created_ts) VALUES ($1, $2, $3, $4)"
const selectDeviceByTokenSQL = "" + const selectDeviceByTokenSQL = "" +
"SELECT device_id, localpart FROM devices WHERE access_token = $1" "SELECT device_id, localpart FROM device_devices WHERE access_token = $1"
const deleteDeviceSQL = "" + const deleteDeviceSQL = "" +
"DELETE FROM devices WHERE device_id = $1 AND localpart = $2" "DELETE FROM device_devices WHERE device_id = $1 AND localpart = $2"
// TODO: List devices? // TODO: List devices?

View file

@ -17,13 +17,14 @@ package keydb
import ( import (
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"github.com/lib/pq" "github.com/lib/pq"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
) )
const serverKeysSchema = ` const serverKeysSchema = `
-- A cache of server keys downloaded from remote servers. -- A cache of server keys downloaded from remote servers.
CREATE TABLE IF NOT EXISTS server_keys ( CREATE TABLE IF NOT EXISTS keydb_server_keys (
-- The name of the matrix server the key is for. -- The name of the matrix server the key is for.
server_name TEXT NOT NULL, server_name TEXT NOT NULL,
-- The ID of the server key. -- The ID of the server key.
@ -35,21 +36,21 @@ CREATE TABLE IF NOT EXISTS server_keys (
valid_until_ts BIGINT NOT NULL, valid_until_ts BIGINT NOT NULL,
-- The raw JSON for the server key. -- The raw JSON for the server key.
server_key_json TEXT NOT NULL, server_key_json TEXT NOT NULL,
CONSTRAINT server_keys_unique UNIQUE (server_name, server_key_id) CONSTRAINT keydb_server_keys_unique UNIQUE (server_name, server_key_id)
); );
CREATE INDEX IF NOT EXISTS server_name_and_key_id ON server_keys (server_name_and_key_id); CREATE INDEX IF NOT EXISTS keydb_server_name_and_key_id ON keydb_server_keys (server_name_and_key_id);
` `
const bulkSelectServerKeysSQL = "" + const bulkSelectServerKeysSQL = "" +
"SELECT server_name, server_key_id, server_key_json FROM server_keys" + "SELECT server_name, server_key_id, server_key_json FROM keydb_server_keys" +
" WHERE server_name_and_key_id = ANY($1)" " WHERE server_name_and_key_id = ANY($1)"
const upsertServerKeysSQL = "" + const upsertServerKeysSQL = "" +
"INSERT INTO server_keys (server_name, server_key_id," + "INSERT INTO keydb_server_keys (server_name, server_key_id," +
" server_name_and_key_id, valid_until_ts, server_key_json)" + " server_name_and_key_id, valid_until_ts, server_key_json)" +
" VALUES ($1, $2, $3, $4, $5)" + " VALUES ($1, $2, $3, $4, $5)" +
" ON CONFLICT ON CONSTRAINT server_keys_unique" + " ON CONFLICT ON CONSTRAINT keydb_server_keys_unique" +
" DO UPDATE SET valid_until_ts = $4, server_key_json = $5" " DO UPDATE SET valid_until_ts = $4, server_key_json = $5"
type serverKeyStatements struct { type serverKeyStatements struct {

View file

@ -15,26 +15,27 @@
package common package common
import "database/sql" import "database/sql"
import "strings"
const partitionOffsetsSchema = ` const partitionOffsetsSchema = `
-- The offsets that the server has processed up to. -- The offsets that the server has processed up to.
CREATE TABLE IF NOT EXISTS partition_offsets ( CREATE TABLE IF NOT EXISTS ${prefix}_partition_offsets (
-- The name of the topic. -- The name of the topic.
topic TEXT NOT NULL, topic TEXT NOT NULL,
-- The 32-bit partition ID -- The 32-bit partition ID
partition INTEGER NOT NULL, partition INTEGER NOT NULL,
-- The 64-bit offset. -- The 64-bit offset.
partition_offset BIGINT NOT NULL, partition_offset BIGINT NOT NULL,
CONSTRAINT topic_partition_unique UNIQUE (topic, partition) CONSTRAINT ${prefix}_topic_partition_unique UNIQUE (topic, partition)
); );
` `
const selectPartitionOffsetsSQL = "" + const selectPartitionOffsetsSQL = "" +
"SELECT partition, partition_offset FROM partition_offsets WHERE topic = $1" "SELECT partition, partition_offset FROM ${prefix}_partition_offsets WHERE topic = $1"
const upsertPartitionOffsetsSQL = "" + const upsertPartitionOffsetsSQL = "" +
"INSERT INTO partition_offsets (topic, partition, partition_offset) VALUES ($1, $2, $3)" + "INSERT INTO ${prefix}_partition_offsets (topic, partition, partition_offset) VALUES ($1, $2, $3)" +
" ON CONFLICT ON CONSTRAINT topic_partition_unique" + " ON CONFLICT ON CONSTRAINT ${prefix}_topic_partition_unique" +
" DO UPDATE SET partition_offset = $3" " DO UPDATE SET partition_offset = $3"
// PartitionOffsetStatements represents a set of statements that can be run on a partition_offsets table. // PartitionOffsetStatements represents a set of statements that can be run on a partition_offsets table.
@ -44,15 +45,21 @@ type PartitionOffsetStatements struct {
} }
// Prepare converts the raw SQL statements into prepared statements. // Prepare converts the raw SQL statements into prepared statements.
func (s *PartitionOffsetStatements) Prepare(db *sql.DB) (err error) { // Takes a prefix to prepend to the table name used to store the partition offsets.
_, err = db.Exec(partitionOffsetsSchema) // This allows multiple components to share the same database schema.
func (s *PartitionOffsetStatements) Prepare(db *sql.DB, prefix string) (err error) {
_, err = db.Exec(strings.Replace(partitionOffsetsSchema, "${prefix}", prefix, -1))
if err != nil { if err != nil {
return return
} }
if s.selectPartitionOffsetsStmt, err = db.Prepare(selectPartitionOffsetsSQL); err != nil { if s.selectPartitionOffsetsStmt, err = db.Prepare(
strings.Replace(selectPartitionOffsetsSQL, "${prefix}", prefix, -1),
); err != nil {
return return
} }
if s.upsertPartitionOffsetStmt, err = db.Prepare(upsertPartitionOffsetsSQL); err != nil { if s.upsertPartitionOffsetStmt, err = db.Prepare(
strings.Replace(upsertPartitionOffsetsSQL, "${prefix}", prefix, -1),
); err != nil {
return return
} }
return return

View file

@ -26,7 +26,7 @@ const joinedHostsSchema = `
-- The joined_hosts table stores a list of m.room.member event ids in the -- The joined_hosts table stores a list of m.room.member event ids in the
-- current state for each room where the membership is "join". -- current state for each room where the membership is "join".
-- There will be an entry for every user that is joined to the room. -- There will be an entry for every user that is joined to the room.
CREATE TABLE IF NOT EXISTS joined_hosts ( CREATE TABLE IF NOT EXISTS federationsender_joined_hosts (
-- The string ID of the room. -- The string ID of the room.
room_id TEXT NOT NULL, room_id TEXT NOT NULL,
-- The event ID of the m.room.member join event. -- The event ID of the m.room.member join event.
@ -35,22 +35,22 @@ CREATE TABLE IF NOT EXISTS joined_hosts (
server_name TEXT NOT NULL server_name TEXT NOT NULL
); );
CREATE UNIQUE INDEX IF NOT EXISTS joined_hosts_event_id_idx CREATE UNIQUE INDEX IF NOT EXISTS federatonsender_joined_hosts_event_id_idx
ON joined_hosts (event_id); ON federationsender_joined_hosts (event_id);
CREATE INDEX IF NOT EXISTS joined_hosts_room_id_idx CREATE INDEX IF NOT EXISTS federatonsender_joined_hosts_room_id_idx
ON joined_hosts (room_id) ON federationsender_joined_hosts (room_id)
` `
const insertJoinedHostsSQL = "" + const insertJoinedHostsSQL = "" +
"INSERT INTO joined_hosts (room_id, event_id, server_name)" + "INSERT INTO federationsender_joined_hosts (room_id, event_id, server_name)" +
" VALUES ($1, $2, $3)" " VALUES ($1, $2, $3)"
const deleteJoinedHostsSQL = "" + const deleteJoinedHostsSQL = "" +
"DELETE FROM joined_hosts WHERE event_id = ANY($1)" "DELETE FROM federationsender_joined_hosts WHERE event_id = ANY($1)"
const selectJoinedHostsSQL = "" + const selectJoinedHostsSQL = "" +
"SELECT event_id, server_name FROM joined_hosts" + "SELECT event_id, server_name FROM federationsender_joined_hosts" +
" WHERE room_id = $1" " WHERE room_id = $1"
type joinedHostsStatements struct { type joinedHostsStatements struct {

View file

@ -19,7 +19,7 @@ import (
) )
const roomSchema = ` const roomSchema = `
CREATE TABLE IF NOT EXISTS rooms ( CREATE TABLE IF NOT EXISTS federationsender_rooms (
-- The string ID of the room -- The string ID of the room
room_id TEXT PRIMARY KEY, room_id TEXT PRIMARY KEY,
-- The most recent event state by the room server. -- The most recent event state by the room server.
@ -29,14 +29,14 @@ CREATE TABLE IF NOT EXISTS rooms (
);` );`
const insertRoomSQL = "" + const insertRoomSQL = "" +
"INSERT INTO rooms (room_id, last_event_id) VALUES ($1, '')" + "INSERT INTO federationsender_rooms (room_id, last_event_id) VALUES ($1, '')" +
" ON CONFLICT DO NOTHING" " ON CONFLICT DO NOTHING"
const selectRoomForUpdateSQL = "" + const selectRoomForUpdateSQL = "" +
"SELECT last_event_id FROM rooms WHERE room_id = $1 FOR UPDATE" "SELECT last_event_id FROM federationsender_rooms WHERE room_id = $1 FOR UPDATE"
const updateRoomSQL = "" + const updateRoomSQL = "" +
"UPDATE rooms SET last_event_id = $2 WHERE room_id = $1" "UPDATE federationsender_rooms SET last_event_id = $2 WHERE room_id = $1"
type roomStatements struct { type roomStatements struct {
insertRoomStmt *sql.Stmt insertRoomStmt *sql.Stmt

View file

@ -53,7 +53,7 @@ func (d *Database) prepare() error {
return err return err
} }
if err = d.PartitionOffsetStatements.Prepare(d.db); err != nil { if err = d.PartitionOffsetStatements.Prepare(d.db, "federationsender"); err != nil {
return err return err
} }

View file

@ -25,7 +25,7 @@ import (
const mediaSchema = ` const mediaSchema = `
-- The media_repository table holds metadata for each media file stored and accessible to the local server, -- The media_repository table holds metadata for each media file stored and accessible to the local server,
-- the actual file is stored separately. -- the actual file is stored separately.
CREATE TABLE IF NOT EXISTS media_repository ( CREATE TABLE IF NOT EXISTS mediaapi_media_repository (
-- The id used to refer to the media. -- The id used to refer to the media.
-- For uploads to this server this is a base64-encoded sha256 hash of the file data -- For uploads to this server this is a base64-encoded sha256 hash of the file data
-- For media from remote servers, this can be any unique identifier string -- For media from remote servers, this can be any unique identifier string
@ -45,16 +45,16 @@ CREATE TABLE IF NOT EXISTS media_repository (
-- The user who uploaded the file. Should be a Matrix user ID. -- The user who uploaded the file. Should be a Matrix user ID.
user_id TEXT NOT NULL user_id TEXT NOT NULL
); );
CREATE UNIQUE INDEX IF NOT EXISTS media_repository_index ON media_repository (media_id, media_origin); CREATE UNIQUE INDEX IF NOT EXISTS mediaapi_media_repository_index ON mediaapi_media_repository (media_id, media_origin);
` `
const insertMediaSQL = ` const insertMediaSQL = `
INSERT INTO media_repository (media_id, media_origin, content_type, file_size_bytes, creation_ts, upload_name, base64hash, user_id) INSERT INTO mediaapi_media_repository (media_id, media_origin, content_type, file_size_bytes, creation_ts, upload_name, base64hash, user_id)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
` `
const selectMediaSQL = ` const selectMediaSQL = `
SELECT content_type, file_size_bytes, creation_ts, upload_name, base64hash, user_id FROM media_repository WHERE media_id = $1 AND media_origin = $2 SELECT content_type, file_size_bytes, creation_ts, upload_name, base64hash, user_id FROM mediaapi_media_repository WHERE media_id = $1 AND media_origin = $2
` `
type mediaStatements struct { type mediaStatements struct {

View file

@ -23,9 +23,9 @@ import (
) )
const thumbnailSchema = ` const thumbnailSchema = `
-- The thumbnail table holds metadata for each thumbnail file stored and accessible to the local server, -- The mediaapi_thumbnail table holds metadata for each thumbnail file stored and accessible to the local server,
-- the actual file is stored separately. -- the actual file is stored separately.
CREATE TABLE IF NOT EXISTS thumbnail ( CREATE TABLE IF NOT EXISTS mediaapi_thumbnail (
-- The id used to refer to the media. -- The id used to refer to the media.
-- For uploads to this server this is a base64-encoded sha256 hash of the file data -- For uploads to this server this is a base64-encoded sha256 hash of the file data
-- For media from remote servers, this can be any unique identifier string -- For media from remote servers, this can be any unique identifier string
@ -45,22 +45,22 @@ CREATE TABLE IF NOT EXISTS thumbnail (
-- The resize method used to generate the thumbnail. Can be crop or scale. -- The resize method used to generate the thumbnail. Can be crop or scale.
resize_method TEXT NOT NULL resize_method TEXT NOT NULL
); );
CREATE UNIQUE INDEX IF NOT EXISTS thumbnail_index ON thumbnail (media_id, media_origin, width, height, resize_method); CREATE UNIQUE INDEX IF NOT EXISTS mediaapi_thumbnail_index ON mediaapi_thumbnail (media_id, media_origin, width, height, resize_method);
` `
const insertThumbnailSQL = ` const insertThumbnailSQL = `
INSERT INTO thumbnail (media_id, media_origin, content_type, file_size_bytes, creation_ts, width, height, resize_method) INSERT INTO mediaapi_thumbnail (media_id, media_origin, content_type, file_size_bytes, creation_ts, width, height, resize_method)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
` `
// Note: this selects one specific thumbnail // Note: this selects one specific thumbnail
const selectThumbnailSQL = ` const selectThumbnailSQL = `
SELECT content_type, file_size_bytes, creation_ts FROM thumbnail WHERE media_id = $1 AND media_origin = $2 AND width = $3 AND height = $4 AND resize_method = $5 SELECT content_type, file_size_bytes, creation_ts FROM mediaapi_thumbnail WHERE media_id = $1 AND media_origin = $2 AND width = $3 AND height = $4 AND resize_method = $5
` `
// Note: this selects all thumbnails for a media_origin and media_id // Note: this selects all thumbnails for a media_origin and media_id
const selectThumbnailsSQL = ` const selectThumbnailsSQL = `
SELECT content_type, file_size_bytes, creation_ts, width, height, resize_method FROM thumbnail WHERE media_id = $1 AND media_origin = $2 SELECT content_type, file_size_bytes, creation_ts, width, height, resize_method FROM mediaapi_thumbnail WHERE media_id = $1 AND media_origin = $2
` `
type thumbnailStatements struct { type thumbnailStatements struct {

View file

@ -16,13 +16,14 @@ package storage
import ( import (
"database/sql" "database/sql"
"github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/roomserver/types"
) )
const eventJSONSchema = ` const eventJSONSchema = `
-- Stores the JSON for each event. This kept separate from the main events -- Stores the JSON for each event. This kept separate from the main events
-- table to keep the rows in the main events table small. -- table to keep the rows in the main events table small.
CREATE TABLE IF NOT EXISTS event_json ( CREATE TABLE IF NOT EXISTS roomserver_event_json (
-- Local numeric ID for the event. -- Local numeric ID for the event.
event_nid BIGINT NOT NULL PRIMARY KEY, event_nid BIGINT NOT NULL PRIMARY KEY,
-- The JSON for the event. -- The JSON for the event.
@ -37,14 +38,14 @@ CREATE TABLE IF NOT EXISTS event_json (
` `
const insertEventJSONSQL = "" + const insertEventJSONSQL = "" +
"INSERT INTO event_json (event_nid, event_json) VALUES ($1, $2)" + "INSERT INTO roomserver_event_json (event_nid, event_json) VALUES ($1, $2)" +
" ON CONFLICT DO NOTHING" " ON CONFLICT DO NOTHING"
// Bulk event JSON lookup by numeric event ID. // Bulk event JSON lookup by numeric event ID.
// Sort by the numeric event ID. // Sort by the numeric event ID.
// This means that we can use binary search to lookup by numeric event ID. // This means that we can use binary search to lookup by numeric event ID.
const bulkSelectEventJSONSQL = "" + const bulkSelectEventJSONSQL = "" +
"SELECT event_nid, event_json FROM event_json" + "SELECT event_nid, event_json FROM roomserver_event_json" +
" WHERE event_nid = ANY($1)" + " WHERE event_nid = ANY($1)" +
" ORDER BY event_nid ASC" " ORDER BY event_nid ASC"

View file

@ -16,6 +16,7 @@ package storage
import ( import (
"database/sql" "database/sql"
"github.com/lib/pq" "github.com/lib/pq"
"github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/roomserver/types"
) )
@ -31,29 +32,30 @@ const eventStateKeysSchema = `
-- Other state keys are automatically assigned numeric IDs starting from 2**16. -- Other state keys are automatically assigned numeric IDs starting from 2**16.
-- This leaves room to add more pre-assigned numeric IDs and clearly separates -- This leaves room to add more pre-assigned numeric IDs and clearly separates
-- the automatically assigned IDs from the pre-assigned IDs. -- the automatically assigned IDs from the pre-assigned IDs.
CREATE SEQUENCE IF NOT EXISTS event_state_key_nid_seq START 65536; CREATE SEQUENCE IF NOT EXISTS roomserver_event_state_key_nid_seq START 65536;
CREATE TABLE IF NOT EXISTS event_state_keys ( CREATE TABLE IF NOT EXISTS roomserver_event_state_keys (
-- Local numeric ID for the state key. -- Local numeric ID for the state key.
event_state_key_nid BIGINT PRIMARY KEY DEFAULT nextval('event_state_key_nid_seq'), event_state_key_nid BIGINT PRIMARY KEY DEFAULT nextval('roomserver_event_state_key_nid_seq'),
event_state_key TEXT NOT NULL CONSTRAINT event_state_key_unique UNIQUE event_state_key TEXT NOT NULL CONSTRAINT roomserver_event_state_key_unique UNIQUE
); );
INSERT INTO event_state_keys (event_state_key_nid, event_state_key) VALUES INSERT INTO roomserver_event_state_keys (event_state_key_nid, event_state_key) VALUES
(1, '') ON CONFLICT DO NOTHING; (1, '') ON CONFLICT DO NOTHING;
` `
// Same as insertEventTypeNIDSQL // Same as insertEventTypeNIDSQL
const insertEventStateKeyNIDSQL = "" + const insertEventStateKeyNIDSQL = "" +
"INSERT INTO event_state_keys (event_state_key) VALUES ($1)" + "INSERT INTO roomserver_event_state_keys (event_state_key) VALUES ($1)" +
" ON CONFLICT ON CONSTRAINT event_state_key_unique" + " ON CONFLICT ON CONSTRAINT roomserver_event_state_key_unique" +
" DO NOTHING RETURNING (event_state_key_nid)" " DO NOTHING RETURNING (event_state_key_nid)"
const selectEventStateKeyNIDSQL = "" + const selectEventStateKeyNIDSQL = "" +
"SELECT event_state_key_nid FROM event_state_keys WHERE event_state_key = $1" "SELECT event_state_key_nid FROM roomserver_event_state_keys" +
" WHERE event_state_key = $1"
// Bulk lookup from string state key to numeric ID for that state key. // Bulk lookup from string state key to numeric ID for that state key.
// Takes an array of strings as the query parameter. // Takes an array of strings as the query parameter.
const bulkSelectEventStateKeyNIDSQL = "" + const bulkSelectEventStateKeyNIDSQL = "" +
"SELECT event_state_key, event_state_key_nid FROM event_state_keys" + "SELECT event_state_key, event_state_key_nid FROM roomserver_event_state_keys" +
" WHERE event_state_key = ANY($1)" " WHERE event_state_key = ANY($1)"
type eventStateKeyStatements struct { type eventStateKeyStatements struct {

View file

@ -16,6 +16,7 @@ package storage
import ( import (
"database/sql" "database/sql"
"github.com/lib/pq" "github.com/lib/pq"
"github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/roomserver/types"
) )
@ -43,14 +44,14 @@ const eventTypesSchema = `
-- Other event types are automatically assigned numeric IDs starting from 2**16. -- Other event types are automatically assigned numeric IDs starting from 2**16.
-- This leaves room to add more pre-assigned numeric IDs and clearly separates -- This leaves room to add more pre-assigned numeric IDs and clearly separates
-- the automatically assigned IDs from the pre-assigned IDs. -- the automatically assigned IDs from the pre-assigned IDs.
CREATE SEQUENCE IF NOT EXISTS event_type_nid_seq START 65536; CREATE SEQUENCE IF NOT EXISTS roomserver_event_type_nid_seq START 65536;
CREATE TABLE IF NOT EXISTS event_types ( CREATE TABLE IF NOT EXISTS roomserver_event_types (
-- Local numeric ID for the event type. -- Local numeric ID for the event type.
event_type_nid BIGINT PRIMARY KEY DEFAULT nextval('event_type_nid_seq'), event_type_nid BIGINT PRIMARY KEY DEFAULT nextval('roomserver_event_type_nid_seq'),
-- The string event_type. -- The string event_type.
event_type TEXT NOT NULL CONSTRAINT event_type_unique UNIQUE event_type TEXT NOT NULL CONSTRAINT roomserver_event_type_unique UNIQUE
); );
INSERT INTO event_types (event_type_nid, event_type) VALUES INSERT INTO roomserver_event_types (event_type_nid, event_type) VALUES
(1, 'm.room.create'), (1, 'm.room.create'),
(2, 'm.room.power_levels'), (2, 'm.room.power_levels'),
(3, 'm.room.join_rules'), (3, 'm.room.join_rules'),
@ -74,17 +75,17 @@ INSERT INTO event_types (event_type_nid, event_type) VALUES
// row even though the data doesn't change resulting in unncesssary modifications // row even though the data doesn't change resulting in unncesssary modifications
// to the indexes. // to the indexes.
const insertEventTypeNIDSQL = "" + const insertEventTypeNIDSQL = "" +
"INSERT INTO event_types (event_type) VALUES ($1)" + "INSERT INTO roomserver_event_types (event_type) VALUES ($1)" +
" ON CONFLICT ON CONSTRAINT event_type_unique" + " ON CONFLICT ON CONSTRAINT roomserver_event_type_unique" +
" DO NOTHING RETURNING (event_type_nid)" " DO NOTHING RETURNING (event_type_nid)"
const selectEventTypeNIDSQL = "" + const selectEventTypeNIDSQL = "" +
"SELECT event_type_nid FROM event_types WHERE event_type = $1" "SELECT event_type_nid FROM roomserver_event_types WHERE event_type = $1"
// Bulk lookup from string event type to numeric ID for that event type. // Bulk lookup from string event type to numeric ID for that event type.
// Takes an array of strings as the query parameter. // Takes an array of strings as the query parameter.
const bulkSelectEventTypeNIDSQL = "" + const bulkSelectEventTypeNIDSQL = "" +
"SELECT event_type, event_type_nid FROM event_types" + "SELECT event_type, event_type_nid FROM roomserver_event_types" +
" WHERE event_type = ANY($1)" " WHERE event_type = ANY($1)"
type eventTypeStatements struct { type eventTypeStatements struct {

View file

@ -17,6 +17,7 @@ package storage
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"github.com/lib/pq" "github.com/lib/pq"
"github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
@ -25,10 +26,10 @@ import (
const eventsSchema = ` const eventsSchema = `
-- The events table holds metadata for each event, the actual JSON is stored -- The events table holds metadata for each event, the actual JSON is stored
-- separately to keep the size of the rows small. -- separately to keep the size of the rows small.
CREATE SEQUENCE IF NOT EXISTS event_nid_seq; CREATE SEQUENCE IF NOT EXISTS roomserver_event_nid_seq;
CREATE TABLE IF NOT EXISTS events ( CREATE TABLE IF NOT EXISTS roomserver_events (
-- Local numeric ID for the event. -- Local numeric ID for the event.
event_nid BIGINT PRIMARY KEY DEFAULT nextval('event_nid_seq'), event_nid BIGINT PRIMARY KEY DEFAULT nextval('roomserver_event_nid_seq'),
-- Local numeric ID for the room the event is in. -- Local numeric ID for the room the event is in.
-- This is never 0. -- This is never 0.
room_nid BIGINT NOT NULL, room_nid BIGINT NOT NULL,
@ -53,7 +54,7 @@ CREATE TABLE IF NOT EXISTS events (
-- Used to lookup the numeric ID when processing requests. -- Used to lookup the numeric ID when processing requests.
-- Needed for state resolution. -- Needed for state resolution.
-- An event may only appear in this table once. -- An event may only appear in this table once.
event_id TEXT NOT NULL CONSTRAINT event_id_unique UNIQUE, event_id TEXT NOT NULL CONSTRAINT roomserver_event_id_unique UNIQUE,
-- The sha256 reference hash for the event. -- The sha256 reference hash for the event.
-- Needed for setting reference hashes when sending new events. -- Needed for setting reference hashes when sending new events.
reference_sha256 BYTEA NOT NULL, reference_sha256 BYTEA NOT NULL,
@ -63,54 +64,54 @@ CREATE TABLE IF NOT EXISTS events (
` `
const insertEventSQL = "" + const insertEventSQL = "" +
"INSERT INTO events (room_nid, event_type_nid, event_state_key_nid, event_id, reference_sha256, auth_event_nids, depth)" + "INSERT INTO roomserver_events (room_nid, event_type_nid, event_state_key_nid, event_id, reference_sha256, auth_event_nids, depth)" +
" VALUES ($1, $2, $3, $4, $5, $6, $7)" + " VALUES ($1, $2, $3, $4, $5, $6, $7)" +
" ON CONFLICT ON CONSTRAINT event_id_unique" + " ON CONFLICT ON CONSTRAINT roomserver_event_id_unique" +
" DO NOTHING" + " DO NOTHING" +
" RETURNING event_nid, state_snapshot_nid" " RETURNING event_nid, state_snapshot_nid"
const selectEventSQL = "" + const selectEventSQL = "" +
"SELECT event_nid, state_snapshot_nid FROM events WHERE event_id = $1" "SELECT event_nid, state_snapshot_nid FROM roomserver_events WHERE event_id = $1"
// Bulk lookup of events by string ID. // Bulk lookup of events by string ID.
// Sort by the numeric IDs for event type and state key. // Sort by the numeric IDs for event type and state key.
// This means we can use binary search to lookup entries by type and state key. // This means we can use binary search to lookup entries by type and state key.
const bulkSelectStateEventByIDSQL = "" + const bulkSelectStateEventByIDSQL = "" +
"SELECT event_type_nid, event_state_key_nid, event_nid FROM events" + "SELECT event_type_nid, event_state_key_nid, event_nid FROM roomserver_events" +
" WHERE event_id = ANY($1)" + " WHERE event_id = ANY($1)" +
" ORDER BY event_type_nid, event_state_key_nid ASC" " ORDER BY event_type_nid, event_state_key_nid ASC"
const bulkSelectStateAtEventByIDSQL = "" + const bulkSelectStateAtEventByIDSQL = "" +
"SELECT event_type_nid, event_state_key_nid, event_nid, state_snapshot_nid FROM events" + "SELECT event_type_nid, event_state_key_nid, event_nid, state_snapshot_nid FROM roomserver_events" +
" WHERE event_id = ANY($1)" " WHERE event_id = ANY($1)"
const updateEventStateSQL = "" + const updateEventStateSQL = "" +
"UPDATE events SET state_snapshot_nid = $2 WHERE event_nid = $1" "UPDATE roomserver_events SET state_snapshot_nid = $2 WHERE event_nid = $1"
const selectEventSentToOutputSQL = "" + const selectEventSentToOutputSQL = "" +
"SELECT sent_to_output FROM events WHERE event_nid = $1" "SELECT sent_to_output FROM roomserver_events WHERE event_nid = $1"
const updateEventSentToOutputSQL = "" + const updateEventSentToOutputSQL = "" +
"UPDATE events SET sent_to_output = TRUE WHERE event_nid = $1" "UPDATE roomserver_events SET sent_to_output = TRUE WHERE event_nid = $1"
const selectEventIDSQL = "" + const selectEventIDSQL = "" +
"SELECT event_id FROM events WHERE event_nid = $1" "SELECT event_id FROM roomserver_events WHERE event_nid = $1"
const bulkSelectStateAtEventAndReferenceSQL = "" + const bulkSelectStateAtEventAndReferenceSQL = "" +
"SELECT event_type_nid, event_state_key_nid, event_nid, state_snapshot_nid, event_id, reference_sha256" + "SELECT event_type_nid, event_state_key_nid, event_nid, state_snapshot_nid, event_id, reference_sha256" +
" FROM events WHERE event_nid = ANY($1)" " FROM roomserver_events WHERE event_nid = ANY($1)"
const bulkSelectEventReferenceSQL = "" + const bulkSelectEventReferenceSQL = "" +
"SELECT event_id, reference_sha256 FROM events WHERE event_nid = ANY($1)" "SELECT event_id, reference_sha256 FROM roomserver_events WHERE event_nid = ANY($1)"
const bulkSelectEventIDSQL = "" + const bulkSelectEventIDSQL = "" +
"SELECT event_nid, event_id FROM events WHERE event_nid = ANY($1)" "SELECT event_nid, event_id FROM roomserver_events WHERE event_nid = ANY($1)"
const bulkSelectEventNIDSQL = "" + const bulkSelectEventNIDSQL = "" +
"SELECT event_id, event_nid FROM events WHERE event_id = ANY($1)" "SELECT event_id, event_nid FROM roomserver_events WHERE event_id = ANY($1)"
const selectMaxEventDepthSQL = "" + const selectMaxEventDepthSQL = "" +
"SELECT COALESCE(MAX(depth) + 1, 0) FROM events WHERE event_nid = ANY($1)" "SELECT COALESCE(MAX(depth) + 1, 0) FROM roomserver_events WHERE event_nid = ANY($1)"
type eventStatements struct { type eventStatements struct {
insertEventStmt *sql.Stmt insertEventStmt *sql.Stmt

View file

@ -16,6 +16,7 @@ package storage
import ( import (
"database/sql" "database/sql"
"github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/roomserver/types"
) )
@ -24,14 +25,14 @@ const previousEventSchema = `
-- stored in the events table. -- stored in the events table.
-- This is used to tell if a new event is already referenced by an event in -- This is used to tell if a new event is already referenced by an event in
-- the database. -- the database.
CREATE TABLE IF NOT EXISTS previous_events ( CREATE TABLE IF NOT EXISTS roomserver_previous_events (
-- The string event ID taken from the prev_events key of an event. -- The string event ID taken from the prev_events key of an event.
previous_event_id TEXT NOT NULL, previous_event_id TEXT NOT NULL,
-- The SHA256 reference hash taken from the prev_events key of an event. -- The SHA256 reference hash taken from the prev_events key of an event.
previous_reference_sha256 BYTEA NOT NULL, previous_reference_sha256 BYTEA NOT NULL,
-- A list of numeric event IDs of events that reference this prev_event. -- A list of numeric event IDs of events that reference this prev_event.
event_nids BIGINT[] NOT NULL, event_nids BIGINT[] NOT NULL,
CONSTRAINT previous_event_id_unique UNIQUE (previous_event_id, previous_reference_sha256) CONSTRAINT roomserver_previous_event_id_unique UNIQUE (previous_event_id, previous_reference_sha256)
); );
` `
@ -41,17 +42,17 @@ CREATE TABLE IF NOT EXISTS previous_events (
// This should only be modified while holding a "FOR UPDATE" lock on the row in the rooms table for this room. // This should only be modified while holding a "FOR UPDATE" lock on the row in the rooms table for this room.
// The lock is necessary to avoid data races when checking whether an event is already referenced by another event. // The lock is necessary to avoid data races when checking whether an event is already referenced by another event.
const insertPreviousEventSQL = "" + const insertPreviousEventSQL = "" +
"INSERT INTO previous_events" + "INSERT INTO roomserver_previous_events" +
" (previous_event_id, previous_reference_sha256, event_nids)" + " (previous_event_id, previous_reference_sha256, event_nids)" +
" VALUES ($1, $2, array_append('{}'::bigint[], $3))" + " VALUES ($1, $2, array_append('{}'::bigint[], $3))" +
" ON CONFLICT ON CONSTRAINT previous_event_id_unique" + " ON CONFLICT ON CONSTRAINT roomserver_previous_event_id_unique" +
" DO UPDATE SET event_nids = array_append(previous_events.event_nids, $3)" + " DO UPDATE SET event_nids = array_append(roomserver_previous_events.event_nids, $3)" +
" WHERE $3 != ALL(previous_events.event_nids)" " WHERE $3 != ALL(roomserver_previous_events.event_nids)"
// Check if the event is referenced by another event in the table. // Check if the event is referenced by another event in the table.
// This should only be done while holding a "FOR UPDATE" lock on the row in the rooms table for this room. // This should only be done while holding a "FOR UPDATE" lock on the row in the rooms table for this room.
const selectPreviousEventExistsSQL = "" + const selectPreviousEventExistsSQL = "" +
"SELECT 1 FROM previous_events" + "SELECT 1 FROM roomserver_previous_events" +
" WHERE previous_event_id = $1 AND previous_reference_sha256 = $2" " WHERE previous_event_id = $1 AND previous_reference_sha256 = $2"
type previousEventStatements struct { type previousEventStatements struct {

View file

@ -20,27 +20,27 @@ import (
const roomAliasesSchema = ` const roomAliasesSchema = `
-- Stores room aliases and room IDs they refer to -- Stores room aliases and room IDs they refer to
CREATE TABLE IF NOT EXISTS room_aliases ( CREATE TABLE IF NOT EXISTS roomserver_room_aliases (
-- Alias of the room -- Alias of the room
alias TEXT NOT NULL PRIMARY KEY, alias TEXT NOT NULL PRIMARY KEY,
-- Room ID the alias refers to -- Room ID the alias refers to
room_id TEXT NOT NULL room_id TEXT NOT NULL
); );
CREATE UNIQUE INDEX IF NOT EXISTS room_id_idx ON room_aliases(room_id); CREATE UNIQUE INDEX IF NOT EXISTS roomserver_room_id_idx ON roomserver_room_aliases(room_id);
` `
const insertRoomAliasSQL = "" + const insertRoomAliasSQL = "" +
"INSERT INTO room_aliases (alias, room_id) VALUES ($1, $2)" "INSERT INTO roomserver_room_aliases (alias, room_id) VALUES ($1, $2)"
const selectRoomIDFromAliasSQL = "" + const selectRoomIDFromAliasSQL = "" +
"SELECT room_id FROM room_aliases WHERE alias = $1" "SELECT room_id FROM roomserver_room_aliases WHERE alias = $1"
const selectAliasesFromRoomIDSQL = "" + const selectAliasesFromRoomIDSQL = "" +
"SELECT alias FROM room_aliases WHERE room_id = $1" "SELECT alias FROM roomserver_room_aliases WHERE room_id = $1"
const deleteRoomAliasSQL = "" + const deleteRoomAliasSQL = "" +
"DELETE FROM room_aliases WHERE alias = $1" "DELETE FROM roomserver_room_aliases WHERE alias = $1"
type roomAliasesStatements struct { type roomAliasesStatements struct {
insertRoomAliasStmt *sql.Stmt insertRoomAliasStmt *sql.Stmt

View file

@ -16,17 +16,18 @@ package storage
import ( import (
"database/sql" "database/sql"
"github.com/lib/pq" "github.com/lib/pq"
"github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/roomserver/types"
) )
const roomsSchema = ` const roomsSchema = `
CREATE SEQUENCE IF NOT EXISTS room_nid_seq; CREATE SEQUENCE IF NOT EXISTS roomserver_room_nid_seq;
CREATE TABLE IF NOT EXISTS rooms ( CREATE TABLE IF NOT EXISTS roomserver_rooms (
-- Local numeric ID for the room. -- Local numeric ID for the room.
room_nid BIGINT PRIMARY KEY DEFAULT nextval('room_nid_seq'), room_nid BIGINT PRIMARY KEY DEFAULT nextval('roomserver_room_nid_seq'),
-- Textual ID for the room. -- Textual ID for the room.
room_id TEXT NOT NULL CONSTRAINT room_id_unique UNIQUE, room_id TEXT NOT NULL CONSTRAINT roomserver_room_id_unique UNIQUE,
-- The most recent events in the room that aren't referenced by another event. -- The most recent events in the room that aren't referenced by another event.
-- This list may empty if the server hasn't joined the room yet. -- This list may empty if the server hasn't joined the room yet.
-- (The server will be in that state while it stores the events for the initial state of the room) -- (The server will be in that state while it stores the events for the initial state of the room)
@ -41,21 +42,21 @@ CREATE TABLE IF NOT EXISTS rooms (
// Same as insertEventTypeNIDSQL // Same as insertEventTypeNIDSQL
const insertRoomNIDSQL = "" + const insertRoomNIDSQL = "" +
"INSERT INTO rooms (room_id) VALUES ($1)" + "INSERT INTO roomserver_rooms (room_id) VALUES ($1)" +
" ON CONFLICT ON CONSTRAINT room_id_unique" + " ON CONFLICT ON CONSTRAINT roomserver_room_id_unique" +
" DO NOTHING RETURNING (room_nid)" " DO NOTHING RETURNING (room_nid)"
const selectRoomNIDSQL = "" + const selectRoomNIDSQL = "" +
"SELECT room_nid FROM rooms WHERE room_id = $1" "SELECT room_nid FROM roomserver_rooms WHERE room_id = $1"
const selectLatestEventNIDsSQL = "" + const selectLatestEventNIDsSQL = "" +
"SELECT latest_event_nids, state_snapshot_nid FROM rooms WHERE room_nid = $1" "SELECT latest_event_nids, state_snapshot_nid FROM roomserver_rooms WHERE room_nid = $1"
const selectLatestEventNIDsForUpdateSQL = "" + const selectLatestEventNIDsForUpdateSQL = "" +
"SELECT latest_event_nids, last_event_sent_nid, state_snapshot_nid FROM rooms WHERE room_nid = $1 FOR UPDATE" "SELECT latest_event_nids, last_event_sent_nid, state_snapshot_nid FROM roomserver_rooms WHERE room_nid = $1 FOR UPDATE"
const updateLatestEventNIDsSQL = "" + const updateLatestEventNIDsSQL = "" +
"UPDATE rooms SET latest_event_nids = $2, last_event_sent_nid = $3, state_snapshot_nid = $4 WHERE room_nid = $1" "UPDATE roomserver_rooms SET latest_event_nids = $2, last_event_sent_nid = $3, state_snapshot_nid = $4 WHERE room_nid = $1"
type roomStatements struct { type roomStatements struct {
insertRoomNIDStmt *sql.Stmt insertRoomNIDStmt *sql.Stmt

View file

@ -17,10 +17,11 @@ package storage
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"sort"
"github.com/lib/pq" "github.com/lib/pq"
"github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/util" "github.com/matrix-org/util"
"sort"
) )
const stateDataSchema = ` const stateDataSchema = `
@ -33,8 +34,8 @@ const stateDataSchema = `
-- lookup a specific (type, state_key) pair for an event. It also makes it easy -- lookup a specific (type, state_key) pair for an event. It also makes it easy
-- to read the state for a given state_block_nid ordered by (type, state_key) -- to read the state for a given state_block_nid ordered by (type, state_key)
-- which in turn makes it easier to merge state data blocks. -- which in turn makes it easier to merge state data blocks.
CREATE SEQUENCE IF NOT EXISTS state_block_nid_seq; CREATE SEQUENCE IF NOT EXISTS roomserver_state_block_nid_seq;
CREATE TABLE IF NOT EXISTS state_block ( CREATE TABLE IF NOT EXISTS roomserver_state_block (
-- Local numeric ID for this state data. -- Local numeric ID for this state data.
state_block_nid bigint NOT NULL, state_block_nid bigint NOT NULL,
event_type_nid bigint NOT NULL, event_type_nid bigint NOT NULL,
@ -45,11 +46,11 @@ CREATE TABLE IF NOT EXISTS state_block (
` `
const insertStateDataSQL = "" + const insertStateDataSQL = "" +
"INSERT INTO state_block (state_block_nid, event_type_nid, event_state_key_nid, event_nid)" + "INSERT INTO roomserver_state_block (state_block_nid, event_type_nid, event_state_key_nid, event_nid)" +
" VALUES ($1, $2, $3, $4)" " VALUES ($1, $2, $3, $4)"
const selectNextStateBlockNIDSQL = "" + const selectNextStateBlockNIDSQL = "" +
"SELECT nextval('state_block_nid_seq')" "SELECT nextval('roomserver_state_block_nid_seq')"
// Bulk state lookup by numeric state block ID. // Bulk state lookup by numeric state block ID.
// Sort by the state_block_nid, event_type_nid, event_state_key_nid // Sort by the state_block_nid, event_type_nid, event_state_key_nid
@ -59,7 +60,7 @@ const selectNextStateBlockNIDSQL = "" +
// state data blocks together. // state data blocks together.
const bulkSelectStateBlockEntriesSQL = "" + const bulkSelectStateBlockEntriesSQL = "" +
"SELECT state_block_nid, event_type_nid, event_state_key_nid, event_nid" + "SELECT state_block_nid, event_type_nid, event_state_key_nid, event_nid" +
" FROM state_block WHERE state_block_nid = ANY($1)" + " FROM roomserver_state_block WHERE state_block_nid = ANY($1)" +
" ORDER BY state_block_nid, event_type_nid, event_state_key_nid" " ORDER BY state_block_nid, event_type_nid, event_state_key_nid"
// Bulk state lookup by numeric state block ID. // Bulk state lookup by numeric state block ID.
@ -71,7 +72,7 @@ const bulkSelectStateBlockEntriesSQL = "" +
// actually wanted. // actually wanted.
const bulkSelectFilteredStateBlockEntriesSQL = "" + const bulkSelectFilteredStateBlockEntriesSQL = "" +
"SELECT state_block_nid, event_type_nid, event_state_key_nid, event_nid" + "SELECT state_block_nid, event_type_nid, event_state_key_nid, event_nid" +
" FROM state_block WHERE state_block_nid = ANY($1)" + " FROM roomserver_state_block WHERE state_block_nid = ANY($1)" +
" AND event_type_nid = ANY($2) AND event_state_key_nid = ANY($3)" + " AND event_type_nid = ANY($2) AND event_state_key_nid = ANY($3)" +
" ORDER BY state_block_nid, event_type_nid, event_state_key_nid" " ORDER BY state_block_nid, event_type_nid, event_state_key_nid"

View file

@ -17,6 +17,7 @@ package storage
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"github.com/lib/pq" "github.com/lib/pq"
"github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/roomserver/types"
) )
@ -32,10 +33,10 @@ const stateSnapshotSchema = `
-- because room state tends to accumulate small changes over time. Although if -- because room state tends to accumulate small changes over time. Although if
-- the list of deltas becomes too long it becomes more efficient to encode -- the list of deltas becomes too long it becomes more efficient to encode
-- the full state under single state_block_nid. -- the full state under single state_block_nid.
CREATE SEQUENCE IF NOT EXISTS state_snapshot_nid_seq; CREATE SEQUENCE IF NOT EXISTS roomserver_state_snapshot_nid_seq;
CREATE TABLE IF NOT EXISTS state_snapshots ( CREATE TABLE IF NOT EXISTS roomserver_state_snapshots (
-- Local numeric ID for the state. -- Local numeric ID for the state.
state_snapshot_nid bigint PRIMARY KEY DEFAULT nextval('state_snapshot_nid_seq'), state_snapshot_nid bigint PRIMARY KEY DEFAULT nextval('roomserver_state_snapshot_nid_seq'),
-- Local numeric ID of the room this state is for. -- Local numeric ID of the room this state is for.
-- Unused in normal operation, but useful for background work or ad-hoc debugging. -- Unused in normal operation, but useful for background work or ad-hoc debugging.
room_nid bigint NOT NULL, room_nid bigint NOT NULL,
@ -45,7 +46,7 @@ CREATE TABLE IF NOT EXISTS state_snapshots (
` `
const insertStateSQL = "" + const insertStateSQL = "" +
"INSERT INTO state_snapshots (room_nid, state_block_nids)" + "INSERT INTO roomserver_state_snapshots (room_nid, state_block_nids)" +
" VALUES ($1, $2)" + " VALUES ($1, $2)" +
" RETURNING state_snapshot_nid" " RETURNING state_snapshot_nid"
@ -53,7 +54,7 @@ const insertStateSQL = "" +
// Sorting by state_snapshot_nid means we can use binary search over the result // Sorting by state_snapshot_nid means we can use binary search over the result
// to lookup the state data NIDs for a state snapshot NID. // to lookup the state data NIDs for a state snapshot NID.
const bulkSelectStateBlockNIDsSQL = "" + const bulkSelectStateBlockNIDsSQL = "" +
"SELECT state_snapshot_nid, state_block_nids FROM state_snapshots" + "SELECT state_snapshot_nid, state_block_nids FROM roomserver_state_snapshots" +
" WHERE state_snapshot_nid = ANY($1) ORDER BY state_snapshot_nid ASC" " WHERE state_snapshot_nid = ANY($1) ORDER BY state_snapshot_nid ASC"
type stateSnapshotStatements struct { type stateSnapshotStatements struct {

View file

@ -22,7 +22,7 @@ import (
const accountDataSchema = ` const accountDataSchema = `
-- Stores the users account data -- Stores the users account data
CREATE TABLE IF NOT EXISTS account_data_type ( CREATE TABLE IF NOT EXISTS syncapi_account_data_type (
-- The highest numeric ID from the output_room_events at the time of saving the data -- The highest numeric ID from the output_room_events at the time of saving the data
id BIGINT, id BIGINT,
-- ID of the user the data belongs to -- ID of the user the data belongs to
@ -35,19 +35,19 @@ CREATE TABLE IF NOT EXISTS account_data_type (
PRIMARY KEY(user_id, room_id, type), PRIMARY KEY(user_id, room_id, type),
-- We don't want two entries of the same type for the same user -- We don't want two entries of the same type for the same user
CONSTRAINT account_data_unique UNIQUE (user_id, room_id, type) CONSTRAINT syncapi_account_data_unique UNIQUE (user_id, room_id, type)
); );
CREATE UNIQUE INDEX IF NOT EXISTS account_data_id_idx ON account_data_type(id); CREATE UNIQUE INDEX IF NOT EXISTS syncapi_account_data_id_idx ON syncapi_account_data_type(id);
` `
const insertAccountDataSQL = "" + const insertAccountDataSQL = "" +
"INSERT INTO account_data_type (id, user_id, room_id, type) VALUES ($1, $2, $3, $4)" + "INSERT INTO syncapi_account_data_type (id, user_id, room_id, type) VALUES ($1, $2, $3, $4)" +
" ON CONFLICT ON CONSTRAINT account_data_unique" + " ON CONFLICT ON CONSTRAINT syncapi_account_data_unique" +
" DO UPDATE SET id = EXCLUDED.id" " DO UPDATE SET id = EXCLUDED.id"
const selectAccountDataInRangeSQL = "" + const selectAccountDataInRangeSQL = "" +
"SELECT room_id, type FROM account_data_type" + "SELECT room_id, type FROM syncapi_account_data_type" +
" WHERE user_id = $1 AND id > $2 AND id <= $3" + " WHERE user_id = $1 AND id > $2 AND id <= $3" +
" ORDER BY id ASC" " ORDER BY id ASC"

View file

@ -16,13 +16,14 @@ package storage
import ( import (
"database/sql" "database/sql"
"github.com/lib/pq" "github.com/lib/pq"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
) )
const currentRoomStateSchema = ` const currentRoomStateSchema = `
-- Stores the current room state for every room. -- Stores the current room state for every room.
CREATE TABLE IF NOT EXISTS current_room_state ( CREATE TABLE IF NOT EXISTS syncapi_current_room_state (
-- The 'room_id' key for the state event. -- The 'room_id' key for the state event.
room_id TEXT NOT NULL, room_id TEXT NOT NULL,
-- The state event ID -- The state event ID
@ -40,37 +41,37 @@ CREATE TABLE IF NOT EXISTS current_room_state (
-- part of the current state of the room. -- part of the current state of the room.
added_at BIGINT, added_at BIGINT,
-- Clobber based on 3-uple of room_id, type and state_key -- Clobber based on 3-uple of room_id, type and state_key
CONSTRAINT room_state_unique UNIQUE (room_id, type, state_key) CONSTRAINT syncapi_room_state_unique UNIQUE (room_id, type, state_key)
); );
-- for event deletion -- for event deletion
CREATE UNIQUE INDEX IF NOT EXISTS event_id_idx ON current_room_state(event_id); CREATE UNIQUE INDEX IF NOT EXISTS syncapi_event_id_idx ON syncapi_current_room_state(event_id);
-- for querying membership states of users -- for querying membership states of users
CREATE INDEX IF NOT EXISTS membership_idx ON current_room_state(type, state_key, membership) WHERE membership IS NOT NULL AND membership != 'leave'; CREATE INDEX IF NOT EXISTS syncapi_membership_idx ON syncapi_current_room_state(type, state_key, membership) WHERE membership IS NOT NULL AND membership != 'leave';
` `
const upsertRoomStateSQL = "" + const upsertRoomStateSQL = "" +
"INSERT INTO current_room_state (room_id, event_id, type, state_key, event_json, membership, added_at)" + "INSERT INTO syncapi_current_room_state (room_id, event_id, type, state_key, event_json, membership, added_at)" +
" VALUES ($1, $2, $3, $4, $5, $6, $7)" + " VALUES ($1, $2, $3, $4, $5, $6, $7)" +
" ON CONFLICT ON CONSTRAINT room_state_unique" + " ON CONFLICT ON CONSTRAINT syncapi_room_state_unique" +
" DO UPDATE SET event_id = $2, event_json = $5, membership = $6, added_at = $7" " DO UPDATE SET event_id = $2, event_json = $5, membership = $6, added_at = $7"
const deleteRoomStateByEventIDSQL = "" + const deleteRoomStateByEventIDSQL = "" +
"DELETE FROM current_room_state WHERE event_id = $1" "DELETE FROM syncapi_current_room_state WHERE event_id = $1"
const selectRoomIDsWithMembershipSQL = "" + const selectRoomIDsWithMembershipSQL = "" +
"SELECT room_id FROM current_room_state WHERE type = 'm.room.member' AND state_key = $1 AND membership = $2" "SELECT room_id FROM syncapi_current_room_state WHERE type = 'm.room.member' AND state_key = $1 AND membership = $2"
const selectCurrentStateSQL = "" + const selectCurrentStateSQL = "" +
"SELECT event_json FROM current_room_state WHERE room_id = $1" "SELECT event_json FROM syncapi_current_room_state WHERE room_id = $1"
const selectJoinedUsersSQL = "" + const selectJoinedUsersSQL = "" +
"SELECT room_id, state_key FROM current_room_state WHERE type = 'm.room.member' AND membership = 'join'" "SELECT room_id, state_key FROM syncapi_current_room_state WHERE type = 'm.room.member' AND membership = 'join'"
const selectStateEventSQL = "" + const selectStateEventSQL = "" +
"SELECT event_json FROM current_room_state WHERE type = $1 AND room_id = $2 AND state_key = $3" "SELECT event_json FROM syncapi_current_room_state WHERE type = $1 AND room_id = $2 AND state_key = $3"
const selectEventsWithEventIDsSQL = "" + const selectEventsWithEventIDsSQL = "" +
"SELECT added_at, event_json FROM current_room_state WHERE event_id = ANY($1)" "SELECT added_at, event_json FROM syncapi_current_room_state WHERE event_id = ANY($1)"
type currentRoomStateStatements struct { type currentRoomStateStatements struct {
upsertRoomStateStmt *sql.Stmt upsertRoomStateStmt *sql.Stmt

View file

@ -25,7 +25,7 @@ import (
const outputRoomEventsSchema = ` const outputRoomEventsSchema = `
-- Stores output room events received from the roomserver. -- Stores output room events received from the roomserver.
CREATE TABLE IF NOT EXISTS output_room_events ( CREATE TABLE IF NOT EXISTS syncapi_output_room_events (
-- An incrementing ID which denotes the position in the log that this event resides at. -- An incrementing ID which denotes the position in the log that this event resides at.
-- NB: 'serial' makes no guarantees to increment by 1 every time, only that it increments. -- NB: 'serial' makes no guarantees to increment by 1 every time, only that it increments.
-- This isn't a problem for us since we just want to order by this field. -- This isn't a problem for us since we just want to order by this field.
@ -42,24 +42,29 @@ CREATE TABLE IF NOT EXISTS output_room_events (
remove_state_ids TEXT[] remove_state_ids TEXT[]
); );
-- for event selection -- for event selection
CREATE UNIQUE INDEX IF NOT EXISTS event_id_idx ON output_room_events(event_id); CREATE UNIQUE INDEX IF NOT EXISTS syncapi_event_id_idx ON syncapi_output_room_events(event_id);
` `
const insertEventSQL = "" + const insertEventSQL = "" +
"INSERT INTO output_room_events (room_id, event_id, event_json, add_state_ids, remove_state_ids) VALUES ($1, $2, $3, $4, $5) RETURNING id" "INSERT INTO syncapi_output_room_events (" +
" room_id, event_id, event_json, add_state_ids, remove_state_ids" +
") VALUES ($1, $2, $3, $4, $5) RETURNING id"
const selectEventsSQL = "" + const selectEventsSQL = "" +
"SELECT id, event_json FROM output_room_events WHERE event_id = ANY($1)" "SELECT id, event_json FROM syncapi_output_room_events WHERE event_id = ANY($1)"
const selectRecentEventsSQL = "" + const selectRecentEventsSQL = "" +
"SELECT id, event_json FROM output_room_events WHERE room_id = $1 AND id > $2 AND id <= $3 ORDER BY id DESC LIMIT $4" "SELECT id, event_json FROM syncapi_output_room_events" +
" WHERE room_id = $1 AND id > $2 AND id <= $3" +
" ORDER BY id DESC LIMIT $4"
const selectMaxIDSQL = "" + const selectMaxIDSQL = "" +
"SELECT MAX(id) FROM output_room_events" "SELECT MAX(id) FROM syncapi_output_room_events"
// In order for us to apply the state updates correctly, rows need to be ordered in the order they were received (id). // In order for us to apply the state updates correctly, rows need to be ordered in the order they were received (id).
const selectStateInRangeSQL = "" + const selectStateInRangeSQL = "" +
"SELECT id, event_json, add_state_ids, remove_state_ids FROM output_room_events" + "SELECT id, event_json, add_state_ids, remove_state_ids" +
" FROM syncapi_output_room_events" +
" WHERE (id > $1 AND id <= $2) AND (add_state_ids IS NOT NULL OR remove_state_ids IS NOT NULL)" + " WHERE (id > $1 AND id <= $2) AND (add_state_ids IS NOT NULL OR remove_state_ids IS NOT NULL)" +
" ORDER BY id ASC" " ORDER BY id ASC"

View file

@ -56,7 +56,7 @@ func NewSyncServerDatabase(dataSourceName string) (*SyncServerDatabase, error) {
return nil, err return nil, err
} }
partitions := common.PartitionOffsetStatements{} partitions := common.PartitionOffsetStatements{}
if err = partitions.Prepare(db); err != nil { if err = partitions.Prepare(db, "syncapi"); err != nil {
return nil, err return nil, err
} }
accountData := accountDataStatements{} accountData := accountDataStatements{}