apache / superset

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

Unable to create datasets with snowflake database #30600

Open chrishronek opened 1 month ago

chrishronek commented 1 month ago

Bug description

I'm unable to create datasets in Superset from a Snowflake Database. However, I can query that same table in the SQL Lab with no issues (i.e., select * from cortex.daily_fact works as expected). This issue may not be reproducible locally (because this is a private snowflake instance). However, I was able to get the error locally by running:

  1. git clone https://github.com/apache/superset && cd superset
  2. echo "snowflake-sqlalchemy" >> ./docker/requirements-local.txt
  3. docker compose -f docker-compose-image-tag.yml up --build
  4. Setup my snowflake connection
  5. Click on Datasets >> + Dataset
  6. Selecting the schema and table that I wanted to create a dataset from

Screenshots/recordings

SQL Lab - No Problems Creating the Dataset - Problem The Table in Snowflake

Superset version

4.0.2

Python version

3.10

Node version

Not applicable

Browser

Safari

Additional context

Error in Logs

superset_app          | 2024-10-14 20:43:00,837:DEBUG:superset.stats_logger:[stats_logger] (incr) DatabaseRestApi.table_metadata.error
superset_app          | 2024-10-14 20:43:00,837:ERROR:flask_appbuilder.api:'NullType' object is not callable
superset_app          | Traceback (most recent call last):
superset_app          |   File "/usr/local/lib/python3.10/site-packages/flask_appbuilder/api/__init__.py", line 110, in wraps
superset_app          |     return f(self, *args, **kwargs)
superset_app          |   File "/app/superset/views/base_api.py", line 127, in wraps
superset_app          |     raise ex
superset_app          |   File "/app/superset/views/base_api.py", line 121, in wraps
superset_app          |     duration, response = time_function(f, self, *args, **kwargs)
superset_app          |   File "/app/superset/utils/core.py", line 1470, in time_function
superset_app          |     response = func(*args, **kwargs)
superset_app          |   File "/app/superset/utils/log.py", line 255, in wrapper
superset_app          |     value = f(*args, **kwargs)
superset_app          |   File "/app/superset/databases/api.py", line 742, in table_metadata
superset_app          |     table_info = get_table_metadata(database, table_name, schema_name)
superset_app          |   File "/app/superset/databases/utils.py", line 67, in get_table_metadata
superset_app          |     columns = database.get_columns(table_name, schema_name)
superset_app          |   File "/app/superset/models/core.py", line 839, in get_columns
superset_app          |     return self.db_engine_spec.get_columns(
superset_app          |   File "/app/superset/db_engine_specs/base.py", line 1341, in get_columns
superset_app          |     cast(list[SQLAColumnType], inspector.get_columns(table_name, schema))
superset_app          |   File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/reflection.py", line 497, in get_columns
superset_app          |     col_defs = self.dialect.get_columns(
superset_app          |   File "/usr/local/lib/python3.10/site-packages/snowflake/sqlalchemy/snowdialect.py", line 723, in get_columns
superset_app          |     schema_columns = self._get_schema_columns(connection, schema, **kw)
superset_app          |   File "<string>", line 2, in _get_schema_columns
superset_app          |   File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/reflection.py", line 55, in cache
superset_app          |     ret = fn(self, con, *args, **kw)
superset_app          |   File "/usr/local/lib/python3.10/site-packages/snowflake/sqlalchemy/snowdialect.py", line 592, in _get_schema_columns
superset_app          |     type_instance = col_type(**col_type_kw)
superset_app          | TypeError: 'NullType' object is not callable

Versions

snowflake-sqlalchemy

root@806c33d8de11:/app# pip freeze | grep snowflake
snowflake-connector-python==3.12.2
snowflake-sqlalchemy==1.6.1

superset

root@806c33d8de11:/app# superset version
Loaded your LOCAL configuration at [/app/docker/pythonpath_dev/superset_config.py]
2024-10-14 20:50:08,651:INFO:superset.utils.logging_configurator:logging was configured successfully
2024-10-14 20:50:08,654:INFO:root:Configured event logger of type <class 'superset.utils.log.DBEventLogger'>
/usr/local/lib/python3.10/site-packages/flask_limiter/extension.py:293: UserWarning: Using the in-memory storage for tracking rate limits as no storage was explicitly specified. This is not recommended for production use. See: https://flask-limiter.readthedocs.io#configuring-a-storage-backend for documentation about configuring the storage backend.
  warnings.warn(
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Superset 4.0.2
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Checklist

dosubot[bot] commented 1 month ago

I found a similar closed issue regarding a database driver error when connecting with Snowflake from Superset. The suggested solution was to use the connection string format snowflake://{user}:{password}@{account}.{region}/{database} by dropping the parts after '?' [1].

In your case, the error message 'NullType' object is not callable suggests that there might be an issue with how the Snowflake data types are being mapped to SQLAlchemy types. This could be related to the snowflake-sqlalchemy library's handling of nullable columns, which might be causing a NullType object to be incorrectly instantiated.

You might want to check if there are any updates or patches for the snowflake-sqlalchemy library that address this issue. Additionally, reviewing the data type mappings and ensuring that the Snowflake columns are correctly defined and compatible with SQLAlchemy could help resolve the problem.

To continue talking to Dosu, mention @dosu.

chrishronek commented 1 month ago

Per the dosubot's recommendation, I tried connecting to Snowflake with a URI connection string, and I'm still getting the same error when attempting to create the Dataset.