aboutsummaryrefslogtreecommitdiff
path: root/roomserver/storage/sqlite3/membership_table.go
diff options
context:
space:
mode:
authorKegsay <kegan@matrix.org>2020-02-13 17:27:33 +0000
committerGitHub <noreply@github.com>2020-02-13 17:27:33 +0000
commitb6ea1bc67ab51667b9e139dd05e0778aca025501 (patch)
tree18569c317fd28544144c320ce844d93a8ff8ec5e /roomserver/storage/sqlite3/membership_table.go
parent6942ee1de0250235164cf0ce45570b7fc919669d (diff)
Support sqlite in addition to postgres (#869)
* Move current work into single branch * Initial massaging of clientapi etc (not working yet) * Interfaces for accounts/devices databases * Duplicate postgres package for sqlite3 (no changes made to it yet) * Some keydb, accountdb, devicedb, common partition fixes, some more syncapi tweaking * Fix accounts DB, device DB * Update naffka dependency for SQLite * Naffka SQLite * Update naffka to latest master * SQLite support for federationsender * Mostly not-bad support for SQLite in syncapi (although there are problems where lots of events get classed incorrectly as backward extremities, probably because of IN/ANY clauses that are badly supported) * Update Dockerfile -> Go 1.13.7, add build-base (as gcc and friends are needed for SQLite) * Implement GET endpoints for account_data in clientapi * Nuke filtering for now... * Revert "Implement GET endpoints for account_data in clientapi" This reverts commit 4d80dff4583d278620d9b3ed437e9fcd8d4674ee. * Implement GET endpoints for account_data in clientapi (#861) * Implement GET endpoints for account_data in clientapi * Fix accountDB parameter * Remove fmt.Println * Fix insertAccountData SQLite query * Fix accountDB storage interfaces * Add empty push rules into account data on account creation (#862) * Put SaveAccountData into the right function this time * Not sure if roomserver is better or worse now * sqlite work * Allow empty last sent ID for the first event * sqlite: room creation works * Support sending messages * Nuke fmt.println * Move QueryVariadic etc into common, other device fixes * Fix some linter issues * Fix bugs * Fix some linting errors * Fix errcheck lint errors * Make naffka use postgres as fallback, fix couple of compile errors * What on earth happened to the /rooms/{roomID}/send/{eventType} routing Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
Diffstat (limited to 'roomserver/storage/sqlite3/membership_table.go')
-rw-r--r--roomserver/storage/sqlite3/membership_table.go180
1 files changed, 180 insertions, 0 deletions
diff --git a/roomserver/storage/sqlite3/membership_table.go b/roomserver/storage/sqlite3/membership_table.go
new file mode 100644
index 00000000..97877673
--- /dev/null
+++ b/roomserver/storage/sqlite3/membership_table.go
@@ -0,0 +1,180 @@
+// 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,
+// 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/common"
+ "github.com/matrix-org/dendrite/roomserver/types"
+)
+
+type membershipState int64
+
+const (
+ membershipStateLeaveOrBan membershipState = 1
+ membershipStateInvite membershipState = 2
+ membershipStateJoin membershipState = 3
+)
+
+const membershipSchema = `
+ CREATE TABLE IF NOT EXISTS roomserver_membership (
+ room_nid INTEGER NOT NULL,
+ target_nid INTEGER NOT NULL,
+ sender_nid INTEGER NOT NULL DEFAULT 0,
+ membership_nid INTEGER NOT NULL DEFAULT 1,
+ event_nid INTEGER NOT NULL DEFAULT 0,
+ UNIQUE (room_nid, target_nid)
+ );
+`
+
+// Insert a row in to membership table so that it can be locked by the
+// SELECT FOR UPDATE
+const insertMembershipSQL = "" +
+ "INSERT INTO roomserver_membership (room_nid, target_nid)" +
+ " VALUES ($1, $2)" +
+ " ON CONFLICT DO NOTHING"
+
+const selectMembershipFromRoomAndTargetSQL = "" +
+ "SELECT membership_nid, event_nid FROM roomserver_membership" +
+ " WHERE room_nid = $1 AND target_nid = $2"
+
+const selectMembershipsFromRoomAndMembershipSQL = "" +
+ "SELECT event_nid FROM roomserver_membership" +
+ " WHERE room_nid = $1 AND membership_nid = $2"
+
+const selectMembershipsFromRoomSQL = "" +
+ "SELECT event_nid FROM roomserver_membership" +
+ " WHERE room_nid = $1"
+
+const selectMembershipForUpdateSQL = "" +
+ "SELECT membership_nid FROM roomserver_membership" +
+ " WHERE room_nid = $1 AND target_nid = $2"
+
+const updateMembershipSQL = "" +
+ "UPDATE roomserver_membership SET sender_nid = $1, membership_nid = $2, event_nid = $3" +
+ " WHERE room_nid = $4 AND target_nid = $5"
+
+type membershipStatements struct {
+ insertMembershipStmt *sql.Stmt
+ selectMembershipForUpdateStmt *sql.Stmt
+ selectMembershipFromRoomAndTargetStmt *sql.Stmt
+ selectMembershipsFromRoomAndMembershipStmt *sql.Stmt
+ selectMembershipsFromRoomStmt *sql.Stmt
+ updateMembershipStmt *sql.Stmt
+}
+
+func (s *membershipStatements) prepare(db *sql.DB) (err error) {
+ _, err = db.Exec(membershipSchema)
+ if err != nil {
+ return
+ }
+
+ return statementList{
+ {&s.insertMembershipStmt, insertMembershipSQL},
+ {&s.selectMembershipForUpdateStmt, selectMembershipForUpdateSQL},
+ {&s.selectMembershipFromRoomAndTargetStmt, selectMembershipFromRoomAndTargetSQL},
+ {&s.selectMembershipsFromRoomAndMembershipStmt, selectMembershipsFromRoomAndMembershipSQL},
+ {&s.selectMembershipsFromRoomStmt, selectMembershipsFromRoomSQL},
+ {&s.updateMembershipStmt, updateMembershipSQL},
+ }.prepare(db)
+}
+
+func (s *membershipStatements) insertMembership(
+ ctx context.Context, txn *sql.Tx,
+ roomNID types.RoomNID, targetUserNID types.EventStateKeyNID,
+) error {
+ stmt := common.TxStmt(txn, s.insertMembershipStmt)
+ _, err := stmt.ExecContext(ctx, roomNID, targetUserNID)
+ return err
+}
+
+func (s *membershipStatements) selectMembershipForUpdate(
+ ctx context.Context, txn *sql.Tx,
+ roomNID types.RoomNID, targetUserNID types.EventStateKeyNID,
+) (membership membershipState, err error) {
+ stmt := common.TxStmt(txn, s.selectMembershipForUpdateStmt)
+ err = stmt.QueryRowContext(
+ ctx, roomNID, targetUserNID,
+ ).Scan(&membership)
+ return
+}
+
+func (s *membershipStatements) selectMembershipFromRoomAndTarget(
+ ctx context.Context, txn *sql.Tx,
+ roomNID types.RoomNID, targetUserNID types.EventStateKeyNID,
+) (eventNID types.EventNID, membership membershipState, err error) {
+ selectStmt := common.TxStmt(txn, s.selectMembershipFromRoomAndTargetStmt)
+ err = selectStmt.QueryRowContext(
+ ctx, roomNID, targetUserNID,
+ ).Scan(&membership, &eventNID)
+ return
+}
+
+func (s *membershipStatements) selectMembershipsFromRoom(
+ ctx context.Context, txn *sql.Tx,
+ roomNID types.RoomNID,
+) (eventNIDs []types.EventNID, err error) {
+ selectStmt := common.TxStmt(txn, s.selectMembershipsFromRoomStmt)
+ rows, err := selectStmt.QueryContext(ctx, roomNID)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close() // nolint: errcheck
+
+ for rows.Next() {
+ var eNID types.EventNID
+ if err = rows.Scan(&eNID); err != nil {
+ return
+ }
+ eventNIDs = append(eventNIDs, eNID)
+ }
+ return
+}
+func (s *membershipStatements) selectMembershipsFromRoomAndMembership(
+ ctx context.Context, txn *sql.Tx,
+ roomNID types.RoomNID, membership membershipState,
+) (eventNIDs []types.EventNID, err error) {
+ stmt := common.TxStmt(txn, s.selectMembershipsFromRoomAndMembershipStmt)
+ rows, err := stmt.QueryContext(ctx, roomNID, membership)
+ if err != nil {
+ return
+ }
+ defer rows.Close() // nolint: errcheck
+
+ for rows.Next() {
+ var eNID types.EventNID
+ if err = rows.Scan(&eNID); err != nil {
+ return
+ }
+ eventNIDs = append(eventNIDs, eNID)
+ }
+ return
+}
+
+func (s *membershipStatements) updateMembership(
+ ctx context.Context, txn *sql.Tx,
+ roomNID types.RoomNID, targetUserNID types.EventStateKeyNID,
+ senderUserNID types.EventStateKeyNID, membership membershipState,
+ eventNID types.EventNID,
+) error {
+ stmt := common.TxStmt(txn, s.updateMembershipStmt)
+ _, err := stmt.ExecContext(
+ ctx, senderUserNID, membership, eventNID, roomNID, targetUserNID,
+ )
+ return err
+}