prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Timing out when connecting to a MSSQL database on non-default port using ODBC driver
  I had to use "Microsoft SQL Server (ODBC)" data source because the "Microsoft SQL Server" one does not currently support using SSL. However, when trying to connect to my server on a port different than 1433, connection timed out.
  
  After a bit of digging, I found this:
  > Microsoft's ODBC drivers for SQL Server do not use a PORT= parameter. The port number, if any, is appended to the server name/IP with a comma
  
  source: https://stackoverflow.com/a/50051708/1277401
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `redash/query_runner/mssql_odbc.py`
  Content:
  ```
  1 import logging
  2 import sys
  3 import uuid
  4 
  5 from redash.query_runner import *
  6 from redash.query_runner.mssql import types_map
  7 from redash.utils import json_dumps, json_loads
  8 
  9 logger = logging.getLogger(__name__)
  10 
  11 try:
  12     import pyodbc
  13 
  14     enabled = True
  15 except ImportError:
  16     enabled = False
  17 
  18 
  19 class SQLServerODBC(BaseSQLQueryRunner):
  20     should_annotate_query = False
  21     noop_query = "SELECT 1"
  22 
  23     @classmethod
  24     def configuration_schema(cls):
  25         return {
  26             "type": "object",
  27             "properties": {
  28                 "server": {"type": "string"},
  29                 "port": {"type": "number", "default": 1433},
  30                 "user": {"type": "string"},
  31                 "password": {"type": "string"},
  32                 "db": {"type": "string", "title": "Database Name"},
  33                 "charset": {
  34                     "type": "string",
  35                     "default": "UTF-8",
  36                     "title": "Character Set",
  37                 },
  38                 "use_ssl": {"type": "boolean", "title": "Use SSL", "default": False,},
  39                 "verify_ssl": {
  40                     "type": "boolean",
  41                     "title": "Verify SSL certificate",
  42                     "default": True,
  43                 },
  44             },
  45             "order": [
  46                 "server",
  47                 "port",
  48                 "user",
  49                 "password",
  50                 "db",
  51                 "charset",
  52                 "use_ssl",
  53                 "verify_ssl",
  54             ],
  55             "required": ["server", "user", "password", "db"],
  56             "secret": ["password"],
  57             "extra_options": ["verify_ssl", "use_ssl"],
  58         }
  59 
  60     @classmethod
  61     def enabled(cls):
  62         return enabled
  63 
  64     @classmethod
  65     def name(cls):
  66         return "Microsoft SQL Server (ODBC)"
  67 
  68     @classmethod
  69     def type(cls):
  70         return "mssql_odbc"
  71 
  72     @property
  73     def supports_auto_limit(self):
  74         return False
  75 
  76     def _get_tables(self, schema):
  77         query = """
  78         SELECT table_schema, table_name, column_name
  79         FROM INFORMATION_SCHEMA.COLUMNS
  80         WHERE table_schema NOT IN ('guest','INFORMATION_SCHEMA','sys','db_owner','db_accessadmin'
  81                                   ,'db_securityadmin','db_ddladmin','db_backupoperator','db_datareader'
  82                                   ,'db_datawriter','db_denydatareader','db_denydatawriter'
  83                                   );
  84         """
  85 
  86         results, error = self.run_query(query, None)
  87 
  88         if error is not None:
  89             self._handle_run_query_error(error)
  90 
  91         results = json_loads(results)
  92 
  93         for row in results["rows"]:
  94             if row["table_schema"] != self.configuration["db"]:
  95                 table_name = "{}.{}".format(row["table_schema"], row["table_name"])
  96             else:
  97                 table_name = row["table_name"]
  98 
  99             if table_name not in schema:
  100                 schema[table_name] = {"name": table_name, "columns": []}
  101 
  102             schema[table_name]["columns"].append(row["column_name"])
  103 
  104         return list(schema.values())
  105 
  106     def run_query(self, query, user):
  107         connection = None
  108 
  109         try:
  110             server = self.configuration.get("server")
  111             user = self.configuration.get("user", "")
  112             password = self.configuration.get("password", "")
  113             db = self.configuration["db"]
  114             port = self.configuration.get("port", 1433)
  115             charset = self.configuration.get("charset", "UTF-8")
  116 
  117             connection_string_fmt = "DRIVER={{ODBC Driver 17 for SQL Server}};PORT={};SERVER={};DATABASE={};UID={};PWD={}"
  118             connection_string = connection_string_fmt.format(
  119                 port, server, db, user, password
  120             )
  121 
  122             if self.configuration.get("use_ssl", False):
  123                 connection_string += ";Encrypt=YES"
  124 
  125                 if not self.configuration.get("verify_ssl"):
  126                     connection_string += ";TrustServerCertificate=YES"
  127 
  128             connection = pyodbc.connect(connection_string)
  129             cursor = connection.cursor()
  130             logger.debug("SQLServerODBC running query: %s", query)
  131             cursor.execute(query)
  132             data = cursor.fetchall()
  133 
  134             if cursor.description is not None:
  135                 columns = self.fetch_columns(
  136                     [(i[0], types_map.get(i[1], None)) for i in cursor.description]
  137                 )
  138                 rows = [
  139                     dict(zip((column["name"] for column in columns), row))
  140                     for row in data
  141                 ]
  142 
  143                 data = {"columns": columns, "rows": rows}
  144                 json_data = json_dumps(data)
  145                 error = None
  146             else:
  147                 error = "No data was returned."
  148                 json_data = None
  149 
  150             cursor.close()
  151         except pyodbc.Error as e:
  152             try:
  153                 # Query errors are at `args[1]`
  154                 error = e.args[1]
  155             except IndexError:
  156                 # Connection errors are `args[0][1]`
  157                 error = e.args[0][1]
  158             json_data = None
  159         except (KeyboardInterrupt, JobTimeoutException):
  160             connection.cancel()
  161             raise
  162         finally:
  163             if connection:
  164                 connection.close()
  165 
  166         return json_data, error
  167 
  168 
  169 register(SQLServerODBC)
  170
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/redash/query_runner/mssql_odbc.py b/redash/query_runner/mssql_odbc.py
  --- a/redash/query_runner/mssql_odbc.py
  +++ b/redash/query_runner/mssql_odbc.py
  @@ -114,9 +114,9 @@
               port = self.configuration.get("port", 1433)
               charset = self.configuration.get("charset", "UTF-8")
   
  -            connection_string_fmt = "DRIVER={{ODBC Driver 17 for SQL Server}};PORT={};SERVER={};DATABASE={};UID={};PWD={}"
  +            connection_string_fmt = "DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={},{};DATABASE={};UID={};PWD={}"
               connection_string = connection_string_fmt.format(
  -                port, server, db, user, password
  +                server, port, db, user, password
               )
   
               if self.configuration.get("use_ssl", False):
  
verification_info: {"golden_diff": "diff --git a/redash/query_runner/mssql_odbc.py b/redash/query_runner/mssql_odbc.py\n--- a/redash/query_runner/mssql_odbc.py\n+++ b/redash/query_runner/mssql_odbc.py\n@@ -114,9 +114,9 @@\n             port = self.configuration.get(\"port\", 1433)\n             charset = self.configuration.get(\"charset\", \"UTF-8\")\n \n-            connection_string_fmt = \"DRIVER={{ODBC Driver 17 for SQL Server}};PORT={};SERVER={};DATABASE={};UID={};PWD={}\"\n+            connection_string_fmt = \"DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={},{};DATABASE={};UID={};PWD={}\"\n             connection_string = connection_string_fmt.format(\n-                port, server, db, user, password\n+                server, port, db, user, password\n             )\n \n             if self.configuration.get(\"use_ssl\", False):\n", "issue": "Timing out when connecting to a MSSQL database on non-default port using ODBC driver\nI had to use \"Microsoft SQL Server (ODBC)\" data source because the \"Microsoft SQL Server\" one does not currently support using SSL. However, when trying to connect to my server on a port different than 1433, connection timed out.\r\n\r\nAfter a bit of digging, I found this:\r\n> Microsoft's ODBC drivers for SQL Server do not use a PORT= parameter. The port number, if any, is appended to the server name/IP with a comma\r\n\r\nsource: https://stackoverflow.com/a/50051708/1277401\n", "before_files": [{"content": "import logging\nimport sys\nimport uuid\n\nfrom redash.query_runner import *\nfrom redash.query_runner.mssql import types_map\nfrom redash.utils import json_dumps, json_loads\n\nlogger = logging.getLogger(__name__)\n\ntry:\n    import pyodbc\n\n    enabled = True\nexcept ImportError:\n    enabled = False\n\n\nclass SQLServerODBC(BaseSQLQueryRunner):\n    should_annotate_query = False\n    noop_query = \"SELECT 1\"\n\n    @classmethod\n    def configuration_schema(cls):\n        return {\n            \"type\": \"object\",\n            \"properties\": {\n                \"server\": {\"type\": \"string\"},\n                \"port\": {\"type\": \"number\", \"default\": 1433},\n                \"user\": {\"type\": \"string\"},\n                \"password\": {\"type\": \"string\"},\n                \"db\": {\"type\": \"string\", \"title\": \"Database Name\"},\n                \"charset\": {\n                    \"type\": \"string\",\n                    \"default\": \"UTF-8\",\n                    \"title\": \"Character Set\",\n                },\n                \"use_ssl\": {\"type\": \"boolean\", \"title\": \"Use SSL\", \"default\": False,},\n                \"verify_ssl\": {\n                    \"type\": \"boolean\",\n                    \"title\": \"Verify SSL certificate\",\n                    \"default\": True,\n                },\n            },\n            \"order\": [\n                \"server\",\n                \"port\",\n                \"user\",\n                \"password\",\n                \"db\",\n                \"charset\",\n                \"use_ssl\",\n                \"verify_ssl\",\n            ],\n            \"required\": [\"server\", \"user\", \"password\", \"db\"],\n            \"secret\": [\"password\"],\n            \"extra_options\": [\"verify_ssl\", \"use_ssl\"],\n        }\n\n    @classmethod\n    def enabled(cls):\n        return enabled\n\n    @classmethod\n    def name(cls):\n        return \"Microsoft SQL Server (ODBC)\"\n\n    @classmethod\n    def type(cls):\n        return \"mssql_odbc\"\n\n    @property\n    def supports_auto_limit(self):\n        return False\n\n    def _get_tables(self, schema):\n        query = \"\"\"\n        SELECT table_schema, table_name, column_name\n        FROM INFORMATION_SCHEMA.COLUMNS\n        WHERE table_schema NOT IN ('guest','INFORMATION_SCHEMA','sys','db_owner','db_accessadmin'\n                                  ,'db_securityadmin','db_ddladmin','db_backupoperator','db_datareader'\n                                  ,'db_datawriter','db_denydatareader','db_denydatawriter'\n                                  );\n        \"\"\"\n\n        results, error = self.run_query(query, None)\n\n        if error is not None:\n            self._handle_run_query_error(error)\n\n        results = json_loads(results)\n\n        for row in results[\"rows\"]:\n            if row[\"table_schema\"] != self.configuration[\"db\"]:\n                table_name = \"{}.{}\".format(row[\"table_schema\"], row[\"table_name\"])\n            else:\n                table_name = row[\"table_name\"]\n\n            if table_name not in schema:\n                schema[table_name] = {\"name\": table_name, \"columns\": []}\n\n            schema[table_name][\"columns\"].append(row[\"column_name\"])\n\n        return list(schema.values())\n\n    def run_query(self, query, user):\n        connection = None\n\n        try:\n            server = self.configuration.get(\"server\")\n            user = self.configuration.get(\"user\", \"\")\n            password = self.configuration.get(\"password\", \"\")\n            db = self.configuration[\"db\"]\n            port = self.configuration.get(\"port\", 1433)\n            charset = self.configuration.get(\"charset\", \"UTF-8\")\n\n            connection_string_fmt = \"DRIVER={{ODBC Driver 17 for SQL Server}};PORT={};SERVER={};DATABASE={};UID={};PWD={}\"\n            connection_string = connection_string_fmt.format(\n                port, server, db, user, password\n            )\n\n            if self.configuration.get(\"use_ssl\", False):\n                connection_string += \";Encrypt=YES\"\n\n                if not self.configuration.get(\"verify_ssl\"):\n                    connection_string += \";TrustServerCertificate=YES\"\n\n            connection = pyodbc.connect(connection_string)\n            cursor = connection.cursor()\n            logger.debug(\"SQLServerODBC running query: %s\", query)\n            cursor.execute(query)\n            data = cursor.fetchall()\n\n            if cursor.description is not None:\n                columns = self.fetch_columns(\n                    [(i[0], types_map.get(i[1], None)) for i in cursor.description]\n                )\n                rows = [\n                    dict(zip((column[\"name\"] for column in columns), row))\n                    for row in data\n                ]\n\n                data = {\"columns\": columns, \"rows\": rows}\n                json_data = json_dumps(data)\n                error = None\n            else:\n                error = \"No data was returned.\"\n                json_data = None\n\n            cursor.close()\n        except pyodbc.Error as e:\n            try:\n                # Query errors are at `args[1]`\n                error = e.args[1]\n            except IndexError:\n                # Connection errors are `args[0][1]`\n                error = e.args[0][1]\n            json_data = None\n        except (KeyboardInterrupt, JobTimeoutException):\n            connection.cancel()\n            raise\n        finally:\n            if connection:\n                connection.close()\n\n        return json_data, error\n\n\nregister(SQLServerODBC)\n", "path": "redash/query_runner/mssql_odbc.py"}], "after_files": [{"content": "import logging\nimport sys\nimport uuid\n\nfrom redash.query_runner import *\nfrom redash.query_runner.mssql import types_map\nfrom redash.utils import json_dumps, json_loads\n\nlogger = logging.getLogger(__name__)\n\ntry:\n    import pyodbc\n\n    enabled = True\nexcept ImportError:\n    enabled = False\n\n\nclass SQLServerODBC(BaseSQLQueryRunner):\n    should_annotate_query = False\n    noop_query = \"SELECT 1\"\n\n    @classmethod\n    def configuration_schema(cls):\n        return {\n            \"type\": \"object\",\n            \"properties\": {\n                \"server\": {\"type\": \"string\"},\n                \"port\": {\"type\": \"number\", \"default\": 1433},\n                \"user\": {\"type\": \"string\"},\n                \"password\": {\"type\": \"string\"},\n                \"db\": {\"type\": \"string\", \"title\": \"Database Name\"},\n                \"charset\": {\n                    \"type\": \"string\",\n                    \"default\": \"UTF-8\",\n                    \"title\": \"Character Set\",\n                },\n                \"use_ssl\": {\"type\": \"boolean\", \"title\": \"Use SSL\", \"default\": False,},\n                \"verify_ssl\": {\n                    \"type\": \"boolean\",\n                    \"title\": \"Verify SSL certificate\",\n                    \"default\": True,\n                },\n            },\n            \"order\": [\n                \"server\",\n                \"port\",\n                \"user\",\n                \"password\",\n                \"db\",\n                \"charset\",\n                \"use_ssl\",\n                \"verify_ssl\",\n            ],\n            \"required\": [\"server\", \"user\", \"password\", \"db\"],\n            \"secret\": [\"password\"],\n            \"extra_options\": [\"verify_ssl\", \"use_ssl\"],\n        }\n\n    @classmethod\n    def enabled(cls):\n        return enabled\n\n    @classmethod\n    def name(cls):\n        return \"Microsoft SQL Server (ODBC)\"\n\n    @classmethod\n    def type(cls):\n        return \"mssql_odbc\"\n\n    @property\n    def supports_auto_limit(self):\n        return False\n\n    def _get_tables(self, schema):\n        query = \"\"\"\n        SELECT table_schema, table_name, column_name\n        FROM INFORMATION_SCHEMA.COLUMNS\n        WHERE table_schema NOT IN ('guest','INFORMATION_SCHEMA','sys','db_owner','db_accessadmin'\n                                  ,'db_securityadmin','db_ddladmin','db_backupoperator','db_datareader'\n                                  ,'db_datawriter','db_denydatareader','db_denydatawriter'\n                                  );\n        \"\"\"\n\n        results, error = self.run_query(query, None)\n\n        if error is not None:\n            self._handle_run_query_error(error)\n\n        results = json_loads(results)\n\n        for row in results[\"rows\"]:\n            if row[\"table_schema\"] != self.configuration[\"db\"]:\n                table_name = \"{}.{}\".format(row[\"table_schema\"], row[\"table_name\"])\n            else:\n                table_name = row[\"table_name\"]\n\n            if table_name not in schema:\n                schema[table_name] = {\"name\": table_name, \"columns\": []}\n\n            schema[table_name][\"columns\"].append(row[\"column_name\"])\n\n        return list(schema.values())\n\n    def run_query(self, query, user):\n        connection = None\n\n        try:\n            server = self.configuration.get(\"server\")\n            user = self.configuration.get(\"user\", \"\")\n            password = self.configuration.get(\"password\", \"\")\n            db = self.configuration[\"db\"]\n            port = self.configuration.get(\"port\", 1433)\n            charset = self.configuration.get(\"charset\", \"UTF-8\")\n\n            connection_string_fmt = \"DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={},{};DATABASE={};UID={};PWD={}\"\n            connection_string = connection_string_fmt.format(\n                server, port, db, user, password\n            )\n\n            if self.configuration.get(\"use_ssl\", False):\n                connection_string += \";Encrypt=YES\"\n\n                if not self.configuration.get(\"verify_ssl\"):\n                    connection_string += \";TrustServerCertificate=YES\"\n\n            connection = pyodbc.connect(connection_string)\n            cursor = connection.cursor()\n            logger.debug(\"SQLServerODBC running query: %s\", query)\n            cursor.execute(query)\n            data = cursor.fetchall()\n\n            if cursor.description is not None:\n                columns = self.fetch_columns(\n                    [(i[0], types_map.get(i[1], None)) for i in cursor.description]\n                )\n                rows = [\n                    dict(zip((column[\"name\"] for column in columns), row))\n                    for row in data\n                ]\n\n                data = {\"columns\": columns, \"rows\": rows}\n                json_data = json_dumps(data)\n                error = None\n            else:\n                error = \"No data was returned.\"\n                json_data = None\n\n            cursor.close()\n        except pyodbc.Error as e:\n            try:\n                # Query errors are at `args[1]`\n                error = e.args[1]\n            except IndexError:\n                # Connection errors are `args[0][1]`\n                error = e.args[0][1]\n            json_data = None\n        except (KeyboardInterrupt, JobTimeoutException):\n            connection.cancel()\n            raise\n        finally:\n            if connection:\n                connection.close()\n\n        return json_data, error\n\n\nregister(SQLServerODBC)\n", "path": "redash/query_runner/mssql_odbc.py"}]}