Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Require py36, Postgres 9.6, and sqlite 3.22 #9766

Merged
merged 7 commits into from
Apr 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .buildkite/scripts/test_old_deps.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash

# this script is run by buildkite in a plain `xenial` container; it installs the
# this script is run by buildkite in a plain `bionic` container; it installs the
# minimal requirements for tox and hands over to the py3-old tox environment.

set -ex
Expand Down
1 change: 1 addition & 0 deletions changelog.d/9766.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Synapse now requires Python 3.6 or later. It also requires Postgres 9.6 or later or SQLite 3.22 or later.
2 changes: 0 additions & 2 deletions scripts-dev/build_debian_packages
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@ import threading
from concurrent.futures import ThreadPoolExecutor

DISTS = (
"debian:stretch",
"debian:buster",
"debian:bullseye",
"debian:sid",
"ubuntu:xenial",
"ubuntu:bionic",
"ubuntu:focal",
"ubuntu:groovy",
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def exec_file(path_segments):
zip_safe=False,
long_description=long_description,
long_description_content_type="text/x-rst",
python_requires="~=3.5",
python_requires="~=3.6",
classifiers=[
"Development Status :: 5 - Production/Stable",
"Topic :: Communications :: Chat",
Expand Down
63 changes: 6 additions & 57 deletions synapse/storage/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -2059,69 +2059,18 @@ def make_in_list_sql_clause(
KV = TypeVar("KV")


def make_tuple_comparison_clause(
database_engine: BaseDatabaseEngine, keys: List[Tuple[str, KV]]
) -> Tuple[str, List[KV]]:
def make_tuple_comparison_clause(keys: List[Tuple[str, KV]]) -> Tuple[str, List[KV]]:
"""Returns a tuple comparison SQL clause

Depending what the SQL engine supports, builds a SQL clause that looks like either
"(a, b) > (?, ?)", or "(a > ?) OR (a == ? AND b > ?)".
Builds a SQL clause that looks like "(a, b) > (?, ?)"

Args:
database_engine
keys: A set of (column, value) pairs to be compared.

Returns:
A tuple of SQL query and the args
"""
if database_engine.supports_tuple_comparison:
return (
"(%s) > (%s)" % (",".join(k[0] for k in keys), ",".join("?" for _ in keys)),
[k[1] for k in keys],
)

# we want to build a clause
# (a > ?) OR
# (a == ? AND b > ?) OR
# (a == ? AND b == ? AND c > ?)
# ...
# (a == ? AND b == ? AND ... AND z > ?)
#
# or, equivalently:
#
# (a > ? OR (a == ? AND
# (b > ? OR (b == ? AND
# ...
# (y > ? OR (y == ? AND
# z > ?
# ))
# ...
# ))
# ))
#
# which itself is equivalent to (and apparently easier for the query optimiser):
#
# (a >= ? AND (a > ? OR
# (b >= ? AND (b > ? OR
# ...
# (y >= ? AND (y > ? OR
# z > ?
# ))
# ...
# ))
# ))
#
#

clause = ""
args = [] # type: List[KV]
for k, v in keys[:-1]:
clause = clause + "(%s >= ? AND (%s > ? OR " % (k, k)
args.extend([v, v])

(k, v) = keys[-1]
clause += "%s > ?" % (k,)
args.append(v)

clause += "))" * (len(keys) - 1)
return clause, args
return (
"(%s) > (%s)" % (",".join(k[0] for k in keys), ",".join("?" for _ in keys)),
[k[1] for k in keys],
)
1 change: 0 additions & 1 deletion synapse/storage/databases/main/client_ips.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,6 @@ def _devices_last_seen_update_txn(txn):
# times, which is fine.

where_clause, where_args = make_tuple_comparison_clause(
self.database_engine,
[("user_id", last_user_id), ("device_id", last_device_id)],
)

Expand Down
2 changes: 1 addition & 1 deletion synapse/storage/databases/main/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@ async def _remove_duplicate_outbound_pokes(self, progress, batch_size):

def _txn(txn):
clause, args = make_tuple_comparison_clause(
self.db_pool.engine, [(x, last_row[x]) for x in KEY_COLS]
[(x, last_row[x]) for x in KEY_COLS]
)
sql = """
SELECT stream_id, destination, user_id, device_id, MAX(ts) AS ts
Expand Down
1 change: 0 additions & 1 deletion synapse/storage/databases/main/events_bg_updates.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,6 @@ def _calculate_chain_cover_txn(
# We want to do a `(topological_ordering, stream_ordering) > (?,?)`
# comparison, but that is not supported on older SQLite versions
tuple_clause, tuple_args = make_tuple_comparison_clause(
self.database_engine,
[
("events.room_id", last_room_id),
("topological_ordering", last_depth),
Expand Down
8 changes: 0 additions & 8 deletions synapse/storage/engines/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,6 @@ def can_native_upsert(self) -> bool:
"""
...

@property
@abc.abstractmethod
def supports_tuple_comparison(self) -> bool:
"""
Do we support comparing tuples, i.e. `(a, b) > (c, d)`?
"""
...

@property
@abc.abstractmethod
def supports_using_any_list(self) -> bool:
Expand Down
11 changes: 2 additions & 9 deletions synapse/storage/engines/postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ def check_database(self, db_conn, allow_outdated_version: bool = False):
self._version = db_conn.server_version

# Are we on a supported PostgreSQL version?
if not allow_outdated_version and self._version < 90500:
raise RuntimeError("Synapse requires PostgreSQL 9.5+ or above.")
if not allow_outdated_version and self._version < 90600:
raise RuntimeError("Synapse requires PostgreSQL 9.6 or above.")

with db_conn.cursor() as txn:
txn.execute("SHOW SERVER_ENCODING")
Expand Down Expand Up @@ -129,13 +129,6 @@ def can_native_upsert(self):
"""
return True

@property
def supports_tuple_comparison(self):
"""
Do we support comparing tuples, i.e. `(a, b) > (c, d)`?
"""
return True

@property
def supports_using_any_list(self):
"""Do we support using `a = ANY(?)` and passing a list"""
Expand Down
15 changes: 5 additions & 10 deletions synapse/storage/engines/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,6 @@ def can_native_upsert(self):
"""
return self.module.sqlite_version_info >= (3, 24, 0)

@property
def supports_tuple_comparison(self):
"""
Do we support comparing tuples, i.e. `(a, b) > (c, d)`? This requires
SQLite 3.15+.
"""
return self.module.sqlite_version_info >= (3, 15, 0)

@property
def supports_using_any_list(self):
"""Do we support using `a = ANY(?)` and passing a list"""
Expand All @@ -72,8 +64,11 @@ def supports_using_any_list(self):
def check_database(self, db_conn, allow_outdated_version: bool = False):
if not allow_outdated_version:
version = self.module.sqlite_version_info
if version < (3, 11, 0):
raise RuntimeError("Synapse requires sqlite 3.11 or above.")
# Synapse is untested against older SQLite versions, and we don't want
# to let users upgrade to a version of Synapse with broken support for their
# sqlite version, because it risks leaving them with a half-upgraded db.
if version < (3, 22, 0):
raise RuntimeError("Synapse requires sqlite 3.22 or above.")

def check_new_database(self, txn):
"""Gets called when setting up a brand new database. This allows us to
Expand Down
13 changes: 1 addition & 12 deletions tests/storage/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,6 @@ def _stub_db_engine(**kwargs) -> BaseDatabaseEngine:

class TupleComparisonClauseTestCase(unittest.TestCase):
def test_native_tuple_comparison(self):
db_engine = _stub_db_engine(supports_tuple_comparison=True)
clause, args = make_tuple_comparison_clause(db_engine, [("a", 1), ("b", 2)])
clause, args = make_tuple_comparison_clause([("a", 1), ("b", 2)])
self.assertEqual(clause, "(a,b) > (?,?)")
self.assertEqual(args, [1, 2])

def test_emulated_tuple_comparison(self):
db_engine = _stub_db_engine(supports_tuple_comparison=False)
clause, args = make_tuple_comparison_clause(
db_engine, [("a", 1), ("b", 2), ("c", 3)]
)
self.assertEqual(
clause, "(a >= ? AND (a > ? OR (b >= ? AND (b > ? OR c > ?))))"
)
self.assertEqual(args, [1, 1, 2, 2, 3])
14 changes: 6 additions & 8 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
[tox]
envlist = packaging, py35, py36, py37, py38, py39, check_codestyle, check_isort
envlist = packaging, py36, py37, py38, py39, check_codestyle, check_isort

# we require tox>=2.3.2 for the fix to https://github.com/tox-dev/tox/issues/208
minversion = 2.3.2

[base]
deps =
Expand Down Expand Up @@ -48,6 +51,7 @@ deps =
extras =
# install the optional dependendencies for tox environments without
# '-noextras' in their name
# (this requires tox 3)
!noextras: all
test

Expand All @@ -74,8 +78,6 @@ commands =
# we use "env" rather than putting a value in `setenv` so that it is not
# inherited by other tox environments.
#
# keep this in sync with the copy in `testenv:py3-old`.
#
/usr/bin/env COVERAGE_PROCESS_START={toxinidir}/.coveragerc "{envbindir}/trial" {env:TRIAL_FLAGS:} {posargs:tests} {env:TOXSUFFIX:}

# As of twisted 16.4, trial tries to import the tests as a package (previously
Expand Down Expand Up @@ -121,11 +123,7 @@ commands =
# Install Synapse itself. This won't update any libraries.
pip install -e ".[test]"

# we have to duplicate the command from `testenv` rather than refer to it
# as `{[testenv]commands}`, because we run on ubuntu xenial, which has
# tox 2.3.1, and https://github.com/tox-dev/tox/issues/208.
#
/usr/bin/env COVERAGE_PROCESS_START={toxinidir}/.coveragerc "{envbindir}/trial" {env:TRIAL_FLAGS:} {posargs:tests} {env:TOXSUFFIX:}
{[testenv]commands}

[testenv:benchmark]
deps =
Expand Down