apache / superset

Apache Superset is a Data Visualization and Data Exploration Platform
https://superset.apache.org/
Apache License 2.0
62.08k stars 13.62k forks source link

Query history page is not usable in 3.1.2 and 4.0.0, caused by bug in sql_parse.py #28145

Open AutumnSun1996 opened 5 months ago

AutumnSun1996 commented 5 months ago

Bug description

Cannot accesse 'Query history' page, and get empty list with this error:

image

the error comes from sql_parse.py. check the logs below.

How to reproduce the bug

Minimum sample:

  1. Start superset with following docker-compose.yml
    
    version: "3.7"

services: superset: image: apachesuperset.docker.scarf.sh/apache/superset:3.1.2 volumes:

volumes: superset_home: external: false


2. Go localhost:8088, login as admin/admin
3. Add one database, can just use 'sqlite:///superset_home/superset.db?check_same_thread=false'
4. Goto SQL->SQLLab, run some queries.
5. Goto SQL->Query hisory, and the error appears.

### Screenshots/recordings

![image](https://github.com/apache/superset/assets/20429502/6ee84b92-ff36-417f-9991-0d273547db91)

### Superset version

3.1.2

### Python version

3.10

### Node version

Not applicable

### Browser

Chrome

### Additional context

tried both 3.1.2 and 4.0.0, and got same error with slightly different line numbers.

logs from 3.1.2:
```log
Traceback (most recent call last):
  File "/app/superset/views/base.py", line 252, in wraps
    return f(self, *args, **kwargs)
  File "/app/superset/views/base_api.py", line 487, in get_list_headless
    duration, response = time_function(super().get_list_headless, **kwargs)
  File "/app/superset/utils/core.py", line 1463, in time_function
    response = func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/flask_appbuilder/api/__init__.py", line 1613, in get_list_headless
    response[API_RESULT_RES_KEY] = list_model_schema.dump(lst, many=True)
  File "/usr/local/lib/python3.10/site-packages/marshmallow/schema.py", line 557, in dump
    result = self._serialize(processed_obj, many=many)
  File "/usr/local/lib/python3.10/site-packages/marshmallow/schema.py", line 519, in _serialize
    return [
  File "/usr/local/lib/python3.10/site-packages/marshmallow/schema.py", line 520, in <listcomp>
    self._serialize(d, many=False)
  File "/usr/local/lib/python3.10/site-packages/marshmallow/schema.py", line 525, in _serialize
    value = field_obj.serialize(attr_name, obj, accessor=self.get_attribute)
  File "/usr/local/lib/python3.10/site-packages/marshmallow/fields.py", line 344, in serialize
    return self._serialize(value, attr, obj, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/marshmallow/fields.py", line 1991, in _serialize
    return self._serialize_method(obj)
  File "/app/superset/queries/schemas.py", line 76, in get_sql_tables
    return obj.sql_tables
  File "/app/superset/models/sql_lab.py", line 75, in sql_tables
    extract_tables_from_jinja_sql(
  File "/app/superset/sql_parse.py", line 1110, in extract_tables_from_jinja_sql
    | ParsedQuery(
  File "/app/superset/sql_parse.py", line 280, in __init__
    self._parsed = sqlparse.parse(self.stripped())
  File "/app/superset/sql_parse.py", line 517, in stripped
    return self.sql.strip(" \t\r\n;")
AttributeError: 'Template' object has no attribute 'strip'

Checklist

rusackas commented 5 months ago

Hmmm... can't reproduce this one so far. Are you using any particular DB, or doing anything fancy with jinja?

AutumnSun1996 commented 5 months ago

The problem first appears with our test env, which use mysql:8. But I can reproduce it using sqlite, with reproduce steps above, so I think it's related to superset itself. Are u using the same docker-compose.yml? The image digest is sha256:0106a05a9e612df6c5972cc28e4712ff4a9ab2972665bad384aff6e5ef3112c8

AutumnSun1996 commented 5 months ago

and there is no use or modify with jinja, just some simple queries. BTW, I'm now force cast 'self.sql' to str inside the 'ParsedQuery.stripped' method, as a workaround to fix the http api. not sure if it's the right way, but it worked for my case.

dagostinelli commented 5 months ago

I have this same problem. I experienced it during an upgrade. Old superset was based on an older Github commit. New superset is based on whatever is currently in Dockerhub. I backed up the database (Postgres 10) and restored it to the new database (Postgres 10) I performed a superset db upgrade followed by a superset init. I get that exact error in the query history page.

2024-04-24 01:30:07,715:DEBUG:superset.sql_parse:Parsing with sqlparse statement: Template(body=[Output(nodes=[TemplateData(data='SELECT * from t_page\nlimit 10')])])
2024-04-24 01:30:07,715:ERROR:superset.views.base:'Template' object has no attribute 'strip'
Traceback (most recent call last):
  File "/app/superset/views/base.py", line 252, in wraps
    return f(self, *args, **kwargs)
  File "/app/superset/views/base_api.py", line 487, in get_list_headless
    duration, response = time_function(super().get_list_headless, **kwargs)
  File "/app/superset/utils/core.py", line 1463, in time_function
    response = func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/flask_appbuilder/api/__init__.py", line 1613, in get_list_headless
    response[API_RESULT_RES_KEY] = list_model_schema.dump(lst, many=True)
  File "/usr/local/lib/python3.10/site-packages/marshmallow/schema.py", line 557, in dump
    result = self._serialize(processed_obj, many=many)
  File "/usr/local/lib/python3.10/site-packages/marshmallow/schema.py", line 519, in _serialize
   return [
  File "/usr/local/lib/python3.10/site-packages/marshmallow/schema.py", line 520, in <listcomp>
    self._serialize(d, many=False)
  File "/usr/local/lib/python3.10/site-packages/marshmallow/schema.py", line 525, in _serialize
    value = field_obj.serialize(attr_name, obj, accessor=self.get_attribute)
  File "/usr/local/lib/python3.10/site-packages/marshmallow/fields.py", line 344, in serialize
    return self._serialize(value, attr, obj, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/marshmallow/fields.py", line 1991, in _serialize
    return self._serialize_method(obj)
  File "/app/superset/queries/schemas.py", line 76, in get_sql_tables
    return obj.sql_tables
  File "/app/superset/models/sql_lab.py", line 75, in sql_tables
    extract_tables_from_jinja_sql(
  File "/app/superset/sql_parse.py", line 1110, in extract_tables_from_jinja_sql
    | ParsedQuery(
  File "/app/superset/sql_parse.py", line 280, in __init__
    self._parsed = sqlparse.parse(self.stripped())
  File "/app/superset/sql_parse.py", line 517, in stripped
    return self.sql.strip(" \t\r\n;")
AttributeError: 'Template' object has no attribute 'strip'

Here's a screenshot: image

Umkqq commented 5 months ago

I am experiencing the same issue. Using PostgreSQL version 12.18 and docker deployment based on latest superset image. Deployed from scratch and using empty database. Issue is reproduced only when data exists to show on query history page. image

dagostinelli commented 5 months ago

I patched the file with this attached patch and I was able to get it working. I think this is a hack, but it's got me past the problem.

filename: sql_parse.patch

diff --git a/sql_parse.py b/sql_parse.py
index 62a2457..ceba521 100644
--- a/sql_parse.py
+++ b/sql_parse.py
@@ -514,7 +514,7 @@ class ParsedQuery:
         return self._parsed[0].get_type() == "UNKNOWN"

     def stripped(self) -> str:
-        return self.sql.strip(" \t\r\n;")
+        return str(self.sql).strip(" \t\r\n;")

     def strip_comments(self) -> str:
         return sqlparse.format(self.stripped(), strip_comments=True)

I applied it as follows:

cd /app/superset/ &&patch sql_parse.py < sql_parse.patch
Umkqq commented 5 months ago

I patched the file with this attached patch and I was able to get it working. I think this is a hack, but it's got me past the problem.

filename: sql_parse.patch

diff --git a/sql_parse.py b/sql_parse.py
index 62a2457..ceba521 100644
--- a/sql_parse.py
+++ b/sql_parse.py
@@ -514,7 +514,7 @@ class ParsedQuery:
         return self._parsed[0].get_type() == "UNKNOWN"

     def stripped(self) -> str:
-        return self.sql.strip(" \t\r\n;")
+        return str(self.sql).strip(" \t\r\n;")

     def strip_comments(self) -> str:
         return sqlparse.format(self.stripped(), strip_comments=True)

I applied it as follows:

cd /app/superset/ &&patch sql_parse.py < sql_parse.patch

That helped. Thanks a lot!

rusackas commented 5 months ago

Pinging @michael-s-molina @dpgaspar in case they see a better way to provide a generalized fix/migration for others getting stuck. Otherwise, I hope the change above resolves this issue enough for now. 🤞

gthomas-strike commented 5 months ago

We are encountering the same issue with a deployment using the latest 0.12.9 helm chart version

ichux commented 5 months ago

I patched the file with this attached patch and I was able to get it working. I think this is a hack, but it's got me past the problem.

filename: sql_parse.patch

diff --git a/sql_parse.py b/sql_parse.py
index 62a2457..ceba521 100644
--- a/sql_parse.py
+++ b/sql_parse.py
@@ -514,7 +514,7 @@ class ParsedQuery:
         return self._parsed[0].get_type() == "UNKNOWN"

     def stripped(self) -> str:
-        return self.sql.strip(" \t\r\n;")
+        return str(self.sql).strip(" \t\r\n;")

     def strip_comments(self) -> str:
         return sqlparse.format(self.stripped(), strip_comments=True)

I applied it as follows:

cd /app/superset/ &&patch sql_parse.py < sql_parse.patch

This also worked for us but we just linked an edited version back into the container. Thanks

toniphan21 commented 5 months ago

I think this PR will also fix this problem.

vivian-rook commented 4 months ago

This error still appears in an upgrade from superset 3.1.1 (helm chart 0.12.7) to 4.0.1 (helm chart 0.12.11)

Habeeb556 commented 3 months ago

Hopefully we can merge that soon as the issue still exists in the new version 4.0.2, but the sql_parse.patch provided by @dagostinelli has resolved it.

Aaron-ML commented 2 months ago

We are seeing this issue on 4.0.2 also from a fresh deployment.