prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Error running query: datetime.time(13, 52, 27) is not JSON serializable
  My table schema:
  
  ``` sql
  CREATE TABLE F_entrances (
    id SERIAL PRIMARY KEY,
    timeOfEntrance time,
    customerId int REFERENCES D_customers
  );
  ```
  
  (and yes, I committed the horrible sin of camel_case vs underScore.  I'll be fixing that soonish)
  
  The query
  
  ``` sql
  SELECT
  timeofentrance
  FROM F_entrances
  ```
  
  Gives me the error `Error running query: datetime.time(13, 52, 27) is not JSON serializable`.  I worked around it with `to_char` but this seems to be a problem at the [Python layer](http://stackoverflow.com/a/11875813/1216976).
  
  
  --- 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/utils.py`
  Content:
  ```
  1 import cStringIO
  2 import csv
  3 import codecs
  4 import decimal
  5 import datetime
  6 import json
  7 import re
  8 import hashlib
  9 import sqlparse
  10 import pytz
  11 
  12 COMMENTS_REGEX = re.compile("/\*.*?\*/")
  13 
  14 
  15 class SQLMetaData(object):
  16     TABLE_SELECTION_KEYWORDS = ('FROM', 'JOIN', 'LEFT JOIN', 'FULL JOIN', 'RIGHT JOIN', 'CROSS JOIN', 'INNER JOIN',
  17                                 'OUTER JOIN', 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN', 'FULL OUTER JOIN')
  18 
  19     def __init__(self, sql):
  20         self.sql = sql
  21         self.parsed_sql = sqlparse.parse(self.sql)
  22 
  23         self.has_ddl_statements = self._find_ddl_statements()
  24         self.has_non_select_dml_statements = self._find_dml_statements()
  25         self.used_tables = self._find_tables()
  26 
  27     def _find_ddl_statements(self):
  28         for statement in self.parsed_sql:
  29             if len([x for x in statement.flatten() if x.ttype == sqlparse.tokens.DDL]):
  30                 return True
  31 
  32         return False
  33 
  34     def _find_tables(self):
  35         tables = set()
  36         for statement in self.parsed_sql:
  37             tables.update(self.extract_table_names(statement.tokens))
  38 
  39         return tables
  40 
  41     def extract_table_names(self, tokens):
  42         tables = set()
  43         tokens = [t for t in tokens if t.ttype not in (sqlparse.tokens.Whitespace, sqlparse.tokens.Newline)]
  44 
  45         for i in range(len(tokens)):
  46             if tokens[i].is_group():
  47                 tables.update(self.extract_table_names(tokens[i].tokens))
  48             else:
  49                 if tokens[i].ttype == sqlparse.tokens.Keyword and tokens[i].normalized in self.TABLE_SELECTION_KEYWORDS:
  50                     if isinstance(tokens[i + 1], sqlparse.sql.Identifier):
  51                         tables.add(tokens[i + 1].value)
  52 
  53                     if isinstance(tokens[i + 1], sqlparse.sql.IdentifierList):
  54                         tables.update(set([t.value for t in tokens[i+1].get_identifiers()]))
  55         return tables
  56 
  57     def _find_dml_statements(self):
  58         for statement in self.parsed_sql:
  59             for token in statement.flatten():
  60                 if token.ttype == sqlparse.tokens.DML and token.normalized != 'SELECT':
  61                     return True
  62 
  63         return False
  64 
  65 
  66 def utcnow():
  67     """Return datetime.now value with timezone specified.
  68 
  69     Without the timezone data, when the timestamp stored to the database it gets the current timezone of the server,
  70     which leads to errors in calculations.
  71     """
  72     return datetime.datetime.now(pytz.utc)
  73 
  74 def slugify(s):
  75     return re.sub('[^a-z0-9_\-]+', '-', s.lower())
  76 
  77 
  78 def gen_query_hash(sql):
  79     """Returns hash of the given query after stripping all comments, line breaks and multiple
  80     spaces, and lower casing all text.
  81 
  82     TODO: possible issue - the following queries will get the same id:
  83         1. SELECT 1 FROM table WHERE column='Value';
  84         2. SELECT 1 FROM table where column='value';
  85     """
  86     sql = COMMENTS_REGEX.sub("", sql)
  87     sql = "".join(sql.split()).lower()
  88     return hashlib.md5(sql.encode('utf-8')).hexdigest()
  89 
  90 
  91 class JSONEncoder(json.JSONEncoder):
  92     """Custom JSON encoding class, to handle Decimal and datetime.date instances.
  93     """
  94     def default(self, o):
  95         if isinstance(o, decimal.Decimal):
  96             return float(o)
  97 
  98         if isinstance(o, datetime.date):
  99             return o.isoformat()
  100             
  101         super(JSONEncoder, self).default(o)
  102 
  103 
  104 def json_dumps(data):
  105     return json.dumps(data, cls=JSONEncoder)
  106 
  107 
  108 class UnicodeWriter:
  109     """
  110     A CSV writer which will write rows to CSV file "f",
  111     which is encoded in the given encoding.
  112     """
  113     def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
  114         # Redirect output to a queue
  115         self.queue = cStringIO.StringIO()
  116         self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
  117         self.stream = f
  118         self.encoder = codecs.getincrementalencoder(encoding)()
  119 
  120     def _encode_utf8(self, val):
  121         if isinstance(val, (unicode, str)):
  122             return val.encode('utf-8')
  123 
  124         return val
  125 
  126     def writerow(self, row):
  127         self.writer.writerow([self._encode_utf8(s) for s in row])
  128         # Fetch UTF-8 output from the queue ...
  129         data = self.queue.getvalue()
  130         data = data.decode("utf-8")
  131         # ... and reencode it into the target encoding
  132         data = self.encoder.encode(data)
  133         # write to the target stream
  134         self.stream.write(data)
  135         # empty queue
  136         self.queue.truncate(0)
  137 
  138     def writerows(self, rows):
  139         for row in rows:
  140             self.writerow(row)
  141
  ```
  --- 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/utils.py b/redash/utils.py
  --- a/redash/utils.py
  +++ b/redash/utils.py
  @@ -95,7 +95,7 @@
           if isinstance(o, decimal.Decimal):
               return float(o)
   
  -        if isinstance(o, datetime.date):
  +        if isinstance(o, (datetime.date, datetime.time, datetime.timedelta)):
               return o.isoformat()
               
           super(JSONEncoder, self).default(o)
  
verification_info: {"golden_diff": "diff --git a/redash/utils.py b/redash/utils.py\n--- a/redash/utils.py\n+++ b/redash/utils.py\n@@ -95,7 +95,7 @@\n         if isinstance(o, decimal.Decimal):\n             return float(o)\n \n-        if isinstance(o, datetime.date):\n+        if isinstance(o, (datetime.date, datetime.time, datetime.timedelta)):\n             return o.isoformat()\n             \n         super(JSONEncoder, self).default(o)\n", "issue": "Error running query: datetime.time(13, 52, 27) is not JSON serializable\nMy table schema:\n\n``` sql\nCREATE TABLE F_entrances (\n  id SERIAL PRIMARY KEY,\n  timeOfEntrance time,\n  customerId int REFERENCES D_customers\n);\n```\n\n(and yes, I committed the horrible sin of camel_case vs underScore.  I'll be fixing that soonish)\n\nThe query\n\n``` sql\nSELECT\ntimeofentrance\nFROM F_entrances\n```\n\nGives me the error `Error running query: datetime.time(13, 52, 27) is not JSON serializable`.  I worked around it with `to_char` but this seems to be a problem at the [Python layer](http://stackoverflow.com/a/11875813/1216976).\n\n", "before_files": [{"content": "import cStringIO\nimport csv\nimport codecs\nimport decimal\nimport datetime\nimport json\nimport re\nimport hashlib\nimport sqlparse\nimport pytz\n\nCOMMENTS_REGEX = re.compile(\"/\\*.*?\\*/\")\n\n\nclass SQLMetaData(object):\n    TABLE_SELECTION_KEYWORDS = ('FROM', 'JOIN', 'LEFT JOIN', 'FULL JOIN', 'RIGHT JOIN', 'CROSS JOIN', 'INNER JOIN',\n                                'OUTER JOIN', 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN', 'FULL OUTER JOIN')\n\n    def __init__(self, sql):\n        self.sql = sql\n        self.parsed_sql = sqlparse.parse(self.sql)\n\n        self.has_ddl_statements = self._find_ddl_statements()\n        self.has_non_select_dml_statements = self._find_dml_statements()\n        self.used_tables = self._find_tables()\n\n    def _find_ddl_statements(self):\n        for statement in self.parsed_sql:\n            if len([x for x in statement.flatten() if x.ttype == sqlparse.tokens.DDL]):\n                return True\n\n        return False\n\n    def _find_tables(self):\n        tables = set()\n        for statement in self.parsed_sql:\n            tables.update(self.extract_table_names(statement.tokens))\n\n        return tables\n\n    def extract_table_names(self, tokens):\n        tables = set()\n        tokens = [t for t in tokens if t.ttype not in (sqlparse.tokens.Whitespace, sqlparse.tokens.Newline)]\n\n        for i in range(len(tokens)):\n            if tokens[i].is_group():\n                tables.update(self.extract_table_names(tokens[i].tokens))\n            else:\n                if tokens[i].ttype == sqlparse.tokens.Keyword and tokens[i].normalized in self.TABLE_SELECTION_KEYWORDS:\n                    if isinstance(tokens[i + 1], sqlparse.sql.Identifier):\n                        tables.add(tokens[i + 1].value)\n\n                    if isinstance(tokens[i + 1], sqlparse.sql.IdentifierList):\n                        tables.update(set([t.value for t in tokens[i+1].get_identifiers()]))\n        return tables\n\n    def _find_dml_statements(self):\n        for statement in self.parsed_sql:\n            for token in statement.flatten():\n                if token.ttype == sqlparse.tokens.DML and token.normalized != 'SELECT':\n                    return True\n\n        return False\n\n\ndef utcnow():\n    \"\"\"Return datetime.now value with timezone specified.\n\n    Without the timezone data, when the timestamp stored to the database it gets the current timezone of the server,\n    which leads to errors in calculations.\n    \"\"\"\n    return datetime.datetime.now(pytz.utc)\n\ndef slugify(s):\n    return re.sub('[^a-z0-9_\\-]+', '-', s.lower())\n\n\ndef gen_query_hash(sql):\n    \"\"\"Returns hash of the given query after stripping all comments, line breaks and multiple\n    spaces, and lower casing all text.\n\n    TODO: possible issue - the following queries will get the same id:\n        1. SELECT 1 FROM table WHERE column='Value';\n        2. SELECT 1 FROM table where column='value';\n    \"\"\"\n    sql = COMMENTS_REGEX.sub(\"\", sql)\n    sql = \"\".join(sql.split()).lower()\n    return hashlib.md5(sql.encode('utf-8')).hexdigest()\n\n\nclass JSONEncoder(json.JSONEncoder):\n    \"\"\"Custom JSON encoding class, to handle Decimal and datetime.date instances.\n    \"\"\"\n    def default(self, o):\n        if isinstance(o, decimal.Decimal):\n            return float(o)\n\n        if isinstance(o, datetime.date):\n            return o.isoformat()\n            \n        super(JSONEncoder, self).default(o)\n\n\ndef json_dumps(data):\n    return json.dumps(data, cls=JSONEncoder)\n\n\nclass UnicodeWriter:\n    \"\"\"\n    A CSV writer which will write rows to CSV file \"f\",\n    which is encoded in the given encoding.\n    \"\"\"\n    def __init__(self, f, dialect=csv.excel, encoding=\"utf-8\", **kwds):\n        # Redirect output to a queue\n        self.queue = cStringIO.StringIO()\n        self.writer = csv.writer(self.queue, dialect=dialect, **kwds)\n        self.stream = f\n        self.encoder = codecs.getincrementalencoder(encoding)()\n\n    def _encode_utf8(self, val):\n        if isinstance(val, (unicode, str)):\n            return val.encode('utf-8')\n\n        return val\n\n    def writerow(self, row):\n        self.writer.writerow([self._encode_utf8(s) for s in row])\n        # Fetch UTF-8 output from the queue ...\n        data = self.queue.getvalue()\n        data = data.decode(\"utf-8\")\n        # ... and reencode it into the target encoding\n        data = self.encoder.encode(data)\n        # write to the target stream\n        self.stream.write(data)\n        # empty queue\n        self.queue.truncate(0)\n\n    def writerows(self, rows):\n        for row in rows:\n            self.writerow(row)\n", "path": "redash/utils.py"}], "after_files": [{"content": "import cStringIO\nimport csv\nimport codecs\nimport decimal\nimport datetime\nimport json\nimport re\nimport hashlib\nimport sqlparse\nimport pytz\n\nCOMMENTS_REGEX = re.compile(\"/\\*.*?\\*/\")\n\n\nclass SQLMetaData(object):\n    TABLE_SELECTION_KEYWORDS = ('FROM', 'JOIN', 'LEFT JOIN', 'FULL JOIN', 'RIGHT JOIN', 'CROSS JOIN', 'INNER JOIN',\n                                'OUTER JOIN', 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN', 'FULL OUTER JOIN')\n\n    def __init__(self, sql):\n        self.sql = sql\n        self.parsed_sql = sqlparse.parse(self.sql)\n\n        self.has_ddl_statements = self._find_ddl_statements()\n        self.has_non_select_dml_statements = self._find_dml_statements()\n        self.used_tables = self._find_tables()\n\n    def _find_ddl_statements(self):\n        for statement in self.parsed_sql:\n            if len([x for x in statement.flatten() if x.ttype == sqlparse.tokens.DDL]):\n                return True\n\n        return False\n\n    def _find_tables(self):\n        tables = set()\n        for statement in self.parsed_sql:\n            tables.update(self.extract_table_names(statement.tokens))\n\n        return tables\n\n    def extract_table_names(self, tokens):\n        tables = set()\n        tokens = [t for t in tokens if t.ttype not in (sqlparse.tokens.Whitespace, sqlparse.tokens.Newline)]\n\n        for i in range(len(tokens)):\n            if tokens[i].is_group():\n                tables.update(self.extract_table_names(tokens[i].tokens))\n            else:\n                if tokens[i].ttype == sqlparse.tokens.Keyword and tokens[i].normalized in self.TABLE_SELECTION_KEYWORDS:\n                    if isinstance(tokens[i + 1], sqlparse.sql.Identifier):\n                        tables.add(tokens[i + 1].value)\n\n                    if isinstance(tokens[i + 1], sqlparse.sql.IdentifierList):\n                        tables.update(set([t.value for t in tokens[i+1].get_identifiers()]))\n        return tables\n\n    def _find_dml_statements(self):\n        for statement in self.parsed_sql:\n            for token in statement.flatten():\n                if token.ttype == sqlparse.tokens.DML and token.normalized != 'SELECT':\n                    return True\n\n        return False\n\n\ndef utcnow():\n    \"\"\"Return datetime.now value with timezone specified.\n\n    Without the timezone data, when the timestamp stored to the database it gets the current timezone of the server,\n    which leads to errors in calculations.\n    \"\"\"\n    return datetime.datetime.now(pytz.utc)\n\ndef slugify(s):\n    return re.sub('[^a-z0-9_\\-]+', '-', s.lower())\n\n\ndef gen_query_hash(sql):\n    \"\"\"Returns hash of the given query after stripping all comments, line breaks and multiple\n    spaces, and lower casing all text.\n\n    TODO: possible issue - the following queries will get the same id:\n        1. SELECT 1 FROM table WHERE column='Value';\n        2. SELECT 1 FROM table where column='value';\n    \"\"\"\n    sql = COMMENTS_REGEX.sub(\"\", sql)\n    sql = \"\".join(sql.split()).lower()\n    return hashlib.md5(sql.encode('utf-8')).hexdigest()\n\n\nclass JSONEncoder(json.JSONEncoder):\n    \"\"\"Custom JSON encoding class, to handle Decimal and datetime.date instances.\n    \"\"\"\n    def default(self, o):\n        if isinstance(o, decimal.Decimal):\n            return float(o)\n\n        if isinstance(o, (datetime.date, datetime.time, datetime.timedelta)):\n            return o.isoformat()\n            \n        super(JSONEncoder, self).default(o)\n\n\ndef json_dumps(data):\n    return json.dumps(data, cls=JSONEncoder)\n\n\nclass UnicodeWriter:\n    \"\"\"\n    A CSV writer which will write rows to CSV file \"f\",\n    which is encoded in the given encoding.\n    \"\"\"\n    def __init__(self, f, dialect=csv.excel, encoding=\"utf-8\", **kwds):\n        # Redirect output to a queue\n        self.queue = cStringIO.StringIO()\n        self.writer = csv.writer(self.queue, dialect=dialect, **kwds)\n        self.stream = f\n        self.encoder = codecs.getincrementalencoder(encoding)()\n\n    def _encode_utf8(self, val):\n        if isinstance(val, (unicode, str)):\n            return val.encode('utf-8')\n\n        return val\n\n    def writerow(self, row):\n        self.writer.writerow([self._encode_utf8(s) for s in row])\n        # Fetch UTF-8 output from the queue ...\n        data = self.queue.getvalue()\n        data = data.decode(\"utf-8\")\n        # ... and reencode it into the target encoding\n        data = self.encoder.encode(data)\n        # write to the target stream\n        self.stream.write(data)\n        # empty queue\n        self.queue.truncate(0)\n\n    def writerows(self, rows):\n        for row in rows:\n            self.writerow(row)\n", "path": "redash/utils.py"}]}