mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 10:19:08 +00:00
136 lines
3.5 KiB
TypeScript
136 lines
3.5 KiB
TypeScript
// Copyright 2025 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
import { assert } from 'chai';
|
|
import type { WritableDB } from '../../sql/Interface.std.js';
|
|
import { sql } from '../../sql/util.std.js';
|
|
import {
|
|
createDB,
|
|
updateToVersion,
|
|
insertData,
|
|
explain,
|
|
} from './helpers.node.js';
|
|
|
|
describe('SQL/updateToSchemaVersion1520', () => {
|
|
let db: WritableDB;
|
|
|
|
afterEach(() => {
|
|
db.close();
|
|
});
|
|
|
|
describe('hasUnreadPollVotes column', () => {
|
|
it('adds hasUnreadPollVotes column with default value 0', () => {
|
|
db = createDB();
|
|
updateToVersion(db, 1510);
|
|
|
|
const messages = [
|
|
{
|
|
id: 'msg1',
|
|
conversationId: 'conv1',
|
|
type: 'outgoing',
|
|
received_at: 1000,
|
|
sent_at: 1000,
|
|
timestamp: 1000,
|
|
json: JSON.stringify({
|
|
poll: { question: 'Test?' },
|
|
}),
|
|
},
|
|
];
|
|
|
|
insertData(db, 'messages', messages);
|
|
updateToVersion(db, 1520);
|
|
|
|
const result = db
|
|
.prepare("SELECT hasUnreadPollVotes FROM messages WHERE id = 'msg1'")
|
|
.get<{ hasUnreadPollVotes: number }>();
|
|
|
|
assert.strictEqual(result?.hasUnreadPollVotes, 0);
|
|
});
|
|
});
|
|
|
|
describe('messages_unread_poll_votes index', () => {
|
|
it('creates messages_unread_poll_votes index', () => {
|
|
db = createDB();
|
|
updateToVersion(db, 1520);
|
|
|
|
const indexes = db
|
|
.prepare(
|
|
`
|
|
SELECT name FROM sqlite_master
|
|
WHERE type = 'index' AND name = 'messages_unread_poll_votes'
|
|
`
|
|
)
|
|
.all();
|
|
|
|
assert.lengthOf(indexes, 1, 'index should exist');
|
|
});
|
|
|
|
it('uses index for getUnreadPollVotesAndMarkRead UPDATE query', () => {
|
|
db = createDB();
|
|
updateToVersion(db, 1520);
|
|
|
|
const details = explain(
|
|
db,
|
|
sql`
|
|
UPDATE messages
|
|
INDEXED BY messages_unread_poll_votes
|
|
SET hasUnreadPollVotes = 0
|
|
WHERE
|
|
conversationId = ${'test-conv'} AND
|
|
hasUnreadPollVotes = 1 AND
|
|
received_at <= ${5000} AND
|
|
type IS 'outgoing'
|
|
RETURNING id, conversationId, sent_at AS targetTimestamp, type;
|
|
`
|
|
);
|
|
|
|
assert.strictEqual(
|
|
details,
|
|
'SEARCH messages USING COVERING INDEX messages_unread_poll_votes (conversationId=? AND received_at<?)'
|
|
);
|
|
});
|
|
|
|
it('uses index when hasUnreadPollVotes = 1', () => {
|
|
db = createDB();
|
|
updateToVersion(db, 1520);
|
|
|
|
const detailsWithIndex = explain(
|
|
db,
|
|
sql`
|
|
SELECT id FROM messages
|
|
WHERE
|
|
conversationId = ${'test-conv'} AND
|
|
hasUnreadPollVotes = 1 AND
|
|
type IS 'outgoing' AND
|
|
received_at <= ${5000};
|
|
`
|
|
);
|
|
|
|
assert.include(
|
|
detailsWithIndex,
|
|
'messages_unread_poll_votes',
|
|
'should use partial index when hasUnreadPollVotes = 1'
|
|
);
|
|
});
|
|
|
|
it('index includes all required columns and conditions', () => {
|
|
db = createDB();
|
|
updateToVersion(db, 1520);
|
|
|
|
const indexInfo = db
|
|
.prepare(
|
|
`
|
|
SELECT sql FROM sqlite_master
|
|
WHERE type = 'index' AND name = 'messages_unread_poll_votes'
|
|
`
|
|
)
|
|
.get() as { sql: string };
|
|
|
|
assert.include(indexInfo.sql, 'conversationId');
|
|
assert.include(indexInfo.sql, 'received_at');
|
|
assert.include(indexInfo.sql, 'WHERE hasUnreadPollVotes = 1');
|
|
assert.include(indexInfo.sql, "type IS 'outgoing'");
|
|
});
|
|
});
|
|
});
|