Compare commits
12 Commits
develop
...
anoa/simpl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2edc839c23 | ||
|
|
90128dd355 | ||
|
|
efc492ed99 | ||
|
|
1da8f115b5 | ||
|
|
452fc33646 | ||
|
|
1777a21d12 | ||
|
|
da7c7f39c4 | ||
|
|
8346060c06 | ||
|
|
ae08e4cd43 | ||
|
|
2f255be9b2 | ||
|
|
7496a37e03 | ||
|
|
fcf058f564 |
1
changelog.d/13446.misc
Normal file
1
changelog.d/13446.misc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Allow dropping all rows from a database table via the `simple_truncate` storage method.
|
||||||
1
changelog.d/13446.removal
Normal file
1
changelog.d/13446.removal
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Remove the unused `get_users` storage method.
|
||||||
@@ -2108,15 +2108,26 @@ class DatabasePool:
|
|||||||
) -> int:
|
) -> int:
|
||||||
"""Executes a DELETE query on the named table.
|
"""Executes a DELETE query on the named table.
|
||||||
|
|
||||||
Filters rows by the key-value pairs.
|
Filter rows by the key-value pairs.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
table: string giving the table name
|
table: string giving the table name
|
||||||
keyvalues: dict of column names and values to select the row with
|
keyvalues: dict of column names and values to select the row with. Must
|
||||||
|
not be empty.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The number of deleted rows.
|
The number of deleted rows.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: if keyvalues was a falsey value, such as an empty dict.
|
||||||
"""
|
"""
|
||||||
|
if not keyvalues:
|
||||||
|
raise ValueError(
|
||||||
|
"'keyvalues' arg to simple_delete_txn was falsey. If you were trying to "
|
||||||
|
"delete all rows from a database, perhaps try "
|
||||||
|
"DatabasePool.simple_truncate instead?"
|
||||||
|
)
|
||||||
|
|
||||||
sql = "DELETE FROM %s WHERE %s" % (
|
sql = "DELETE FROM %s WHERE %s" % (
|
||||||
table,
|
table,
|
||||||
" AND ".join("%s = ?" % (k,) for k in keyvalues),
|
" AND ".join("%s = ?" % (k,) for k in keyvalues),
|
||||||
@@ -2195,12 +2206,49 @@ class DatabasePool:
|
|||||||
clauses.append("%s = ?" % (key,))
|
clauses.append("%s = ?" % (key,))
|
||||||
values.append(value)
|
values.append(value)
|
||||||
|
|
||||||
if clauses:
|
sql = "%s WHERE %s" % (sql, " AND ".join(clauses))
|
||||||
sql = "%s WHERE %s" % (sql, " AND ".join(clauses))
|
|
||||||
txn.execute(sql, values)
|
txn.execute(sql, values)
|
||||||
|
|
||||||
return txn.rowcount
|
return txn.rowcount
|
||||||
|
|
||||||
|
async def simple_truncate(self, table: str, desc: str) -> None:
|
||||||
|
"""Executes a TRUNCATE query on the given table, deleting all rows.
|
||||||
|
|
||||||
|
SQLite does not support TRUNCATE, thus a 'DELETE FROM table_name' will
|
||||||
|
be used instead. This method does not return the number of rows deleted,
|
||||||
|
as this is not returned by postgres for TRUNCATE commands.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
table: The name of the table to delete all rows from.
|
||||||
|
desc: description of the transaction, for logging and metrics.
|
||||||
|
"""
|
||||||
|
await self.runInteraction(
|
||||||
|
desc, self._simple_truncate_txn, table, db_autocommit=True
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _simple_truncate_txn(
|
||||||
|
txn: LoggingTransaction,
|
||||||
|
table: str,
|
||||||
|
) -> None:
|
||||||
|
"""Executes a TRUNCATE query on the given table, deleting all rows.
|
||||||
|
|
||||||
|
SQLite does not support TRUNCATE, thus a 'DELETE FROM table_name' will
|
||||||
|
be used instead. This method does not return the number of rows deleted,
|
||||||
|
as this is not returned by postgres for TRUNCATE commands.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
txn: Transaction object
|
||||||
|
table: The name of the table to delete all rows from.
|
||||||
|
"""
|
||||||
|
if isinstance(txn.database_engine, PostgresEngine):
|
||||||
|
sql = f"TRUNCATE {table}"
|
||||||
|
else:
|
||||||
|
# SQLite does not support the TRUNCATE command
|
||||||
|
sql = f"DELETE FROM {table}"
|
||||||
|
|
||||||
|
txn.execute(sql)
|
||||||
|
|
||||||
def get_cache_dict(
|
def get_cache_dict(
|
||||||
self,
|
self,
|
||||||
db_conn: LoggingDatabaseConnection,
|
db_conn: LoggingDatabaseConnection,
|
||||||
|
|||||||
@@ -173,26 +173,6 @@ class DataStore(
|
|||||||
# TODO: shouldn't this be moved to `DeviceWorkerStore`?
|
# TODO: shouldn't this be moved to `DeviceWorkerStore`?
|
||||||
return self._device_list_id_gen.get_current_token()
|
return self._device_list_id_gen.get_current_token()
|
||||||
|
|
||||||
async def get_users(self) -> List[JsonDict]:
|
|
||||||
"""Function to retrieve a list of users in users table.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A list of dictionaries representing users.
|
|
||||||
"""
|
|
||||||
return await self.db_pool.simple_select_list(
|
|
||||||
table="users",
|
|
||||||
keyvalues={},
|
|
||||||
retcols=[
|
|
||||||
"name",
|
|
||||||
"password_hash",
|
|
||||||
"is_guest",
|
|
||||||
"admin",
|
|
||||||
"user_type",
|
|
||||||
"deactivated",
|
|
||||||
],
|
|
||||||
desc="get_users",
|
|
||||||
)
|
|
||||||
|
|
||||||
async def get_users_paginate(
|
async def get_users_paginate(
|
||||||
self,
|
self,
|
||||||
start: int,
|
start: int,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# Copyright 2015, 2016 OpenMarket Ltd
|
# Copyright 2015, 2016 OpenMarket Ltd
|
||||||
# Copyright 2019 New Vector Ltd
|
# Copyright 2019 New Vector Ltd
|
||||||
|
# Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -152,3 +153,63 @@ class UpdateUpsertManyTests(unittest.HomeserverTestCase):
|
|||||||
set(self._dump_table_to_tuple()),
|
set(self._dump_table_to_tuple()),
|
||||||
{(1, "alice", "aaa!"), (2, "bob", "bbb!"), (3, "charlie", "C")},
|
{(1, "alice", "aaa!"), (2, "bob", "bbb!"), (3, "charlie", "C")},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleTruncateTestCase(unittest.HomeserverTestCase):
|
||||||
|
"""Tests for the DatabasePool.simple_truncate storage method."""
|
||||||
|
|
||||||
|
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
|
||||||
|
"""Create and populate a database table to run tests against."""
|
||||||
|
self.storage = hs.get_datastores().main
|
||||||
|
self.table_name = "test_database_table"
|
||||||
|
|
||||||
|
self.get_success(
|
||||||
|
self.storage.db_pool.runInteraction(
|
||||||
|
"simple_truncate_test_create",
|
||||||
|
lambda x, *a: x.execute(*a),
|
||||||
|
"CREATE TABLE %s (id INTEGER, value TEXT)" % self.table_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# And add some rows to the table.
|
||||||
|
self.get_success(
|
||||||
|
self.storage.db_pool.simple_insert_many(
|
||||||
|
table=self.table_name,
|
||||||
|
keys=("id", "value"),
|
||||||
|
values=[(1, "A"), (2, "B"), (3, "C")],
|
||||||
|
desc="simple_truncate_test_insert",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_simple_truncate_deletes_all_rows(self) -> None:
|
||||||
|
"""Test that simple_truncate deletes all rows from a database table."""
|
||||||
|
table_rows = self.get_success(
|
||||||
|
self.storage.db_pool.simple_select_list(
|
||||||
|
table=self.table_name,
|
||||||
|
keyvalues=None,
|
||||||
|
retcols=("id",),
|
||||||
|
desc="simple_truncate_test_select",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure the table has some rows for us to test deleting.
|
||||||
|
self.assertGreater(len(table_rows), 0)
|
||||||
|
|
||||||
|
# Attempt to truncate the table
|
||||||
|
self.get_success(
|
||||||
|
self.storage.db_pool.simple_truncate(
|
||||||
|
table=self.table_name,
|
||||||
|
desc="simple_truncate_test_truncate",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Perform another select and ensure there are no remaining rows.
|
||||||
|
table_rows = self.get_success(
|
||||||
|
self.storage.db_pool.simple_select_list(
|
||||||
|
table=self.table_name,
|
||||||
|
keyvalues=None,
|
||||||
|
retcols=("id",),
|
||||||
|
desc="simple_truncate_test_select",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.assertEqual(len(table_rows), 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user