Skip to content

Commit 2859ee1

Browse files
committed
Fix database bugs
- message_views migration code was all sorts of messed up: it wasn't applying on sqlite when it was meant to, and it wasn't actually adding the filtered field that it was checking to see when migration was needed, and didn't have the `seqno` rename. Also the message_details_deleter was missing. - Moved message_views migration to after seqno updates because it depends on `seqno` being there now. - Added `filtered` column to message_metadata in the schema files. - "user" wasn't properly quoted in a couple places - pinned_by had the wrong foreign key on messages. SQLite tests didn't pick this up because FK constraints aren't enforced by default under SQLite (which is moronic). - enable foreign key enforcement on sqlite connections.
1 parent d78b723 commit 2859ee1

File tree

4 files changed

+28
-13
lines changed

4 files changed

+28
-13
lines changed

sogs/db.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,10 @@ def database_init():
132132
migrate_v01x,
133133
add_new_tables,
134134
add_new_columns,
135-
update_message_views,
136135
create_message_details_deleter,
137136
check_for_hacks,
138137
seqno_etc_updates,
138+
update_message_views,
139139
user_perm_future_updates,
140140
):
141141
with transaction(conn):
@@ -228,7 +228,7 @@ def add_new_tables(conn):
228228

229229

230230
def update_message_views(conn):
231-
if engine.name != "sqlite":
231+
if engine.name == "sqlite":
232232
if any(x not in metadata.tables['message_metadata'].c for x in ('whisper_to', 'filtered')):
233233
logging.warning("DB migration: replacing message_metadata/message_details views")
234234
conn.execute("DROP VIEW IF EXISTS message_metadata")
@@ -240,19 +240,30 @@ def update_message_views(conn):
240240
FROM messages
241241
JOIN users uposter ON messages."user" = uposter.id
242242
LEFT JOIN users uwhisper ON messages.whisper = uwhisper.id
243+
"""
244+
)
245+
conn.execute(
246+
"""
247+
CREATE TRIGGER message_details_deleter INSTEAD OF DELETE ON message_details
248+
FOR EACH ROW WHEN OLD.data IS NOT NULL
249+
BEGIN
250+
UPDATE messages SET data = NULL, data_size = NULL, signature = NULL
251+
WHERE id = OLD.id;
252+
END
243253
"""
244254
)
245255
conn.execute(
246256
"""
247257
CREATE VIEW message_metadata AS
248-
SELECT id, room, "user", session_id, posted, edited, updated, filtered, whisper_to,
258+
SELECT id, room, "user", session_id, posted, edited, seqno, filtered, whisper_to,
249259
length(data) AS data_unpadded, data_size, length(signature) as signature_length
250260
FROM message_details
251261
"""
252262
)
253263

254264
return True
255-
# else: don't worry about this for postgresql because initial pg support had the fix
265+
266+
# else: don't worry about this for postgresql because initial pg support had the fix
256267

257268
return False
258269

@@ -342,7 +353,7 @@ def seqno_etc_updates(conn):
342353
"""
343354
CREATE TABLE pinned_messages (
344355
room INTEGER NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
345-
message INTEGER NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
356+
message INTEGER NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
346357
pinned_by INTEGER NOT NULL REFERENCES users(id),
347358
pinned_at FLOAT NOT NULL DEFAULT ((julianday('now') - 2440587.5)*86400.0), /* unix epoch when pinned */
348359
PRIMARY KEY(room, message)
@@ -425,7 +436,7 @@ def seqno_etc_updates(conn):
425436
"""
426437
CREATE TABLE pinned_messages (
427438
room BIGINT NOT NULL REFERENCES rooms ON DELETE CASCADE,
428-
message BIGINT NOT NULL REFERENCES rooms ON DELETE CASCADE,
439+
message BIGINT NOT NULL REFERENCES messages ON DELETE CASCADE,
429440
pinned_by BIGINT NOT NULL REFERENCES users,
430441
pinned_at FLOAT NOT NULL DEFAULT (extract(epoch from now())),
431442
PRIMARY KEY(room, message)
@@ -627,6 +638,10 @@ def sqlite_fix_connect(dbapi_connection, connection_record):
627638
# disable pysqlite's emitting of the BEGIN statement entirely.
628639
# also stops it from emitting COMMIT before any DDL.
629640
dbapi_connection.isolation_level = None
641+
# Enforce foreign keys. It is very sad that this is not default.
642+
cursor = dbapi_connection.cursor()
643+
cursor.execute("PRAGMA foreign_keys=ON")
644+
cursor.close()
630645

631646
@sqlalchemy.event.listens_for(engine, "begin")
632647
def do_begin(conn):

sogs/model/room.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ def get_messages_for(
525525
# - anything directed to us specifically
526526
# - anything we sent (i.e. outbound whispers)
527527
# - non-whispers
528-
"whisper_mods OR whisper = :user OR user = :user OR whisper IS NULL"
528+
'whisper_mods OR whisper = :user OR "user" = :user OR whisper IS NULL'
529529
if mod
530530
# For a regular user we want to see:
531531
# - anything with whisper_to sent to us

sogs/schema.pgsql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ CREATE TABLE rooms (
1717
upload BOOLEAN NOT NULL DEFAULT TRUE, /* Whether file uploads are allowed by default */
1818
CHECK(token SIMILAR TO '[a-zA-Z0-9_-]+')
1919
);
20-
CREATE INDEX rooms_token ON rooms(token);
2120

2221
-- Trigger to expire an old room image attachment when the room image is changed
2322
CREATE OR REPLACE FUNCTION trigger_room_image_expiry()
@@ -90,8 +89,8 @@ EXECUTE PROCEDURE trigger_messages_insert_history();
9089

9190
CREATE TABLE pinned_messages (
9291
room BIGINT NOT NULL REFERENCES rooms ON DELETE CASCADE,
93-
message BIGINT NOT NULL REFERENCES rooms ON DELETE CASCADE,
94-
pinned_by BIGINT NOT NULL REFERENCES users,
92+
message BIGINT NOT NULL REFERENCES messages ON DELETE CASCADE,
93+
pinned_by BIGINT NOT NULL, /* foreign key to users(id) */
9594
pinned_at FLOAT NOT NULL DEFAULT (extract(epoch from now())),
9695
PRIMARY KEY(room, message)
9796
);
@@ -154,6 +153,7 @@ CREATE INDEX users_last_active ON users(last_active);
154153
ALTER TABLE messages ADD CONSTRAINT messages_user_fk FOREIGN KEY ("user") REFERENCES users;
155154
ALTER TABLE messages ADD CONSTRAINT messages_whisper_fk FOREIGN KEY (whisper) REFERENCES users;
156155
ALTER TABLE files ADD CONSTRAINT files_uploader_fk FOREIGN KEY (uploader) REFERENCES users;
156+
ALTER TABLE pinned_messages ADD CONSTRAINT pinned_messages_pinned_by FOREIGN KEY (pinned_by) REFERENCES users;
157157

158158
-- Create a trigger to maintain the implication "admin implies moderator"
159159
CREATE OR REPLACE FUNCTION trigger_user_admins_are_mods()
@@ -194,7 +194,7 @@ EXECUTE PROCEDURE trigger_message_details_deleter();
194194
-- View of `messages` that is useful for manually inspecting table contents by only returning the
195195
-- length (rather than raw bytes) for data/signature.
196196
CREATE VIEW message_metadata AS
197-
SELECT id, room, "user", session_id, posted, edited, seqno, whisper_to,
197+
SELECT id, room, "user", session_id, posted, edited, seqno, filtered, whisper_to,
198198
length(data) AS data_unpadded, data_size, length(signature) as signature_length
199199
FROM message_details;
200200

sogs/schema.sqlite

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ END;
8181

8282
CREATE TABLE pinned_messages (
8383
room INTEGER NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
84-
message INTEGER NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
84+
message INTEGER NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
8585
pinned_by INTEGER NOT NULL REFERENCES users(id),
8686
pinned_at FLOAT NOT NULL DEFAULT ((julianday('now') - 2440587.5)*86400.0), /* unix epoch when pinned */
8787
PRIMARY KEY(room, message)
@@ -165,7 +165,7 @@ END;
165165
-- View of `messages` that is useful for manually inspecting table contents by only returning the
166166
-- length (rather than raw bytes) for data/signature.
167167
CREATE VIEW message_metadata AS
168-
SELECT id, room, user, session_id, posted, edited, seqno, whisper_to,
168+
SELECT id, room, user, session_id, posted, edited, seqno, filtered, whisper_to,
169169
length(data) AS data_unpadded, data_size, length(signature) as signature_length
170170
FROM message_details;
171171

0 commit comments

Comments
 (0)