prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Fatal 'Failed to upgrade database' error on startup
  As of Synapse 1.7.0, when I start synapse with an old database version, I get this rather cryptic error.
  
  </issue>
  <code>
  [start of synapse/storage/engines/sqlite.py]
  1 # -*- coding: utf-8 -*-
  2 # Copyright 2015, 2016 OpenMarket Ltd
  3 #
  4 # Licensed under the Apache License, Version 2.0 (the "License");
  5 # you may not use this file except in compliance with the License.
  6 # You may obtain a copy of the License at
  7 #
  8 #     http://www.apache.org/licenses/LICENSE-2.0
  9 #
  10 # Unless required by applicable law or agreed to in writing, software
  11 # distributed under the License is distributed on an "AS IS" BASIS,
  12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 # See the License for the specific language governing permissions and
  14 # limitations under the License.
  15 
  16 import struct
  17 import threading
  18 
  19 from synapse.storage.prepare_database import prepare_database
  20 
  21 
  22 class Sqlite3Engine(object):
  23     single_threaded = True
  24 
  25     def __init__(self, database_module, database_config):
  26         self.module = database_module
  27 
  28         # The current max state_group, or None if we haven't looked
  29         # in the DB yet.
  30         self._current_state_group_id = None
  31         self._current_state_group_id_lock = threading.Lock()
  32 
  33     @property
  34     def can_native_upsert(self):
  35         """
  36         Do we support native UPSERTs? This requires SQLite3 3.24+, plus some
  37         more work we haven't done yet to tell what was inserted vs updated.
  38         """
  39         return self.module.sqlite_version_info >= (3, 24, 0)
  40 
  41     @property
  42     def supports_tuple_comparison(self):
  43         """
  44         Do we support comparing tuples, i.e. `(a, b) > (c, d)`? This requires
  45         SQLite 3.15+.
  46         """
  47         return self.module.sqlite_version_info >= (3, 15, 0)
  48 
  49     @property
  50     def supports_using_any_list(self):
  51         """Do we support using `a = ANY(?)` and passing a list
  52         """
  53         return False
  54 
  55     def check_database(self, txn):
  56         pass
  57 
  58     def convert_param_style(self, sql):
  59         return sql
  60 
  61     def on_new_connection(self, db_conn):
  62         prepare_database(db_conn, self, config=None)
  63         db_conn.create_function("rank", 1, _rank)
  64 
  65     def is_deadlock(self, error):
  66         return False
  67 
  68     def is_connection_closed(self, conn):
  69         return False
  70 
  71     def lock_table(self, txn, table):
  72         return
  73 
  74     def get_next_state_group_id(self, txn):
  75         """Returns an int that can be used as a new state_group ID
  76         """
  77         # We do application locking here since if we're using sqlite then
  78         # we are a single process synapse.
  79         with self._current_state_group_id_lock:
  80             if self._current_state_group_id is None:
  81                 txn.execute("SELECT COALESCE(max(id), 0) FROM state_groups")
  82                 self._current_state_group_id = txn.fetchone()[0]
  83 
  84             self._current_state_group_id += 1
  85             return self._current_state_group_id
  86 
  87     @property
  88     def server_version(self):
  89         """Gets a string giving the server version. For example: '3.22.0'
  90 
  91         Returns:
  92             string
  93         """
  94         return "%i.%i.%i" % self.module.sqlite_version_info
  95 
  96 
  97 # Following functions taken from: https://github.com/coleifer/peewee
  98 
  99 
  100 def _parse_match_info(buf):
  101     bufsize = len(buf)
  102     return [struct.unpack("@I", buf[i : i + 4])[0] for i in range(0, bufsize, 4)]
  103 
  104 
  105 def _rank(raw_match_info):
  106     """Handle match_info called w/default args 'pcx' - based on the example rank
  107     function http://sqlite.org/fts3.html#appendix_a
  108     """
  109     match_info = _parse_match_info(raw_match_info)
  110     score = 0.0
  111     p, c = match_info[:2]
  112     for phrase_num in range(p):
  113         phrase_info_idx = 2 + (phrase_num * c * 3)
  114         for col_num in range(c):
  115             col_idx = phrase_info_idx + (col_num * 3)
  116             x1, x2 = match_info[col_idx : col_idx + 2]
  117             if x1 > 0:
  118                 score += float(x1) / x2
  119     return score
  120
  [end of synapse/storage/engines/sqlite.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/synapse/storage/engines/sqlite.py b/synapse/storage/engines/sqlite.py
  --- a/synapse/storage/engines/sqlite.py
  +++ b/synapse/storage/engines/sqlite.py
  @@ -25,6 +25,9 @@
       def __init__(self, database_module, database_config):
           self.module = database_module
   
  +        database = database_config.get("args", {}).get("database")
  +        self._is_in_memory = database in (None, ":memory:",)
  +
           # The current max state_group, or None if we haven't looked
           # in the DB yet.
           self._current_state_group_id = None
  @@ -59,7 +62,12 @@
           return sql
   
       def on_new_connection(self, db_conn):
  -        prepare_database(db_conn, self, config=None)
  +        if self._is_in_memory:
  +            # In memory databases need to be rebuilt each time. Ideally we'd
  +            # reuse the same connection as we do when starting up, but that
  +            # would involve using adbapi before we have started the reactor.
  +            prepare_database(db_conn, self, config=None)
  +
           db_conn.create_function("rank", 1, _rank)
   
       def is_deadlock(self, error):
  
verification_info: {"golden_diff": "diff --git a/synapse/storage/engines/sqlite.py b/synapse/storage/engines/sqlite.py\n--- a/synapse/storage/engines/sqlite.py\n+++ b/synapse/storage/engines/sqlite.py\n@@ -25,6 +25,9 @@\n     def __init__(self, database_module, database_config):\n         self.module = database_module\n \n+        database = database_config.get(\"args\", {}).get(\"database\")\n+        self._is_in_memory = database in (None, \":memory:\",)\n+\n         # The current max state_group, or None if we haven't looked\n         # in the DB yet.\n         self._current_state_group_id = None\n@@ -59,7 +62,12 @@\n         return sql\n \n     def on_new_connection(self, db_conn):\n-        prepare_database(db_conn, self, config=None)\n+        if self._is_in_memory:\n+            # In memory databases need to be rebuilt each time. Ideally we'd\n+            # reuse the same connection as we do when starting up, but that\n+            # would involve using adbapi before we have started the reactor.\n+            prepare_database(db_conn, self, config=None)\n+\n         db_conn.create_function(\"rank\", 1, _rank)\n \n     def is_deadlock(self, error):\n", "issue": "Fatal 'Failed to upgrade database' error on startup\nAs of Synapse 1.7.0, when I start synapse with an old database version, I get this rather cryptic error.\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2015, 2016 OpenMarket Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport struct\nimport threading\n\nfrom synapse.storage.prepare_database import prepare_database\n\n\nclass Sqlite3Engine(object):\n    single_threaded = True\n\n    def __init__(self, database_module, database_config):\n        self.module = database_module\n\n        # The current max state_group, or None if we haven't looked\n        # in the DB yet.\n        self._current_state_group_id = None\n        self._current_state_group_id_lock = threading.Lock()\n\n    @property\n    def can_native_upsert(self):\n        \"\"\"\n        Do we support native UPSERTs? This requires SQLite3 3.24+, plus some\n        more work we haven't done yet to tell what was inserted vs updated.\n        \"\"\"\n        return self.module.sqlite_version_info >= (3, 24, 0)\n\n    @property\n    def supports_tuple_comparison(self):\n        \"\"\"\n        Do we support comparing tuples, i.e. `(a, b) > (c, d)`? This requires\n        SQLite 3.15+.\n        \"\"\"\n        return self.module.sqlite_version_info >= (3, 15, 0)\n\n    @property\n    def supports_using_any_list(self):\n        \"\"\"Do we support using `a = ANY(?)` and passing a list\n        \"\"\"\n        return False\n\n    def check_database(self, txn):\n        pass\n\n    def convert_param_style(self, sql):\n        return sql\n\n    def on_new_connection(self, db_conn):\n        prepare_database(db_conn, self, config=None)\n        db_conn.create_function(\"rank\", 1, _rank)\n\n    def is_deadlock(self, error):\n        return False\n\n    def is_connection_closed(self, conn):\n        return False\n\n    def lock_table(self, txn, table):\n        return\n\n    def get_next_state_group_id(self, txn):\n        \"\"\"Returns an int that can be used as a new state_group ID\n        \"\"\"\n        # We do application locking here since if we're using sqlite then\n        # we are a single process synapse.\n        with self._current_state_group_id_lock:\n            if self._current_state_group_id is None:\n                txn.execute(\"SELECT COALESCE(max(id), 0) FROM state_groups\")\n                self._current_state_group_id = txn.fetchone()[0]\n\n            self._current_state_group_id += 1\n            return self._current_state_group_id\n\n    @property\n    def server_version(self):\n        \"\"\"Gets a string giving the server version. For example: '3.22.0'\n\n        Returns:\n            string\n        \"\"\"\n        return \"%i.%i.%i\" % self.module.sqlite_version_info\n\n\n# Following functions taken from: https://github.com/coleifer/peewee\n\n\ndef _parse_match_info(buf):\n    bufsize = len(buf)\n    return [struct.unpack(\"@I\", buf[i : i + 4])[0] for i in range(0, bufsize, 4)]\n\n\ndef _rank(raw_match_info):\n    \"\"\"Handle match_info called w/default args 'pcx' - based on the example rank\n    function http://sqlite.org/fts3.html#appendix_a\n    \"\"\"\n    match_info = _parse_match_info(raw_match_info)\n    score = 0.0\n    p, c = match_info[:2]\n    for phrase_num in range(p):\n        phrase_info_idx = 2 + (phrase_num * c * 3)\n        for col_num in range(c):\n            col_idx = phrase_info_idx + (col_num * 3)\n            x1, x2 = match_info[col_idx : col_idx + 2]\n            if x1 > 0:\n                score += float(x1) / x2\n    return score\n", "path": "synapse/storage/engines/sqlite.py"}]}