From 032848df96adcfebfa88da55686589d186e5d02c Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Tue, 21 Nov 2023 09:52:28 -0500 Subject: [PATCH 1/2] feat(metadb): handle decimals --- superset/extensions/metadb.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/superset/extensions/metadb.py b/superset/extensions/metadb.py index 5b014b7af6642..305ac86dd0a67 100644 --- a/superset/extensions/metadb.py +++ b/superset/extensions/metadb.py @@ -38,6 +38,7 @@ from __future__ import annotations import datetime +import decimal import operator import urllib.parse from collections.abc import Iterator @@ -86,7 +87,7 @@ class SupersetAPSWDialect(APSWDialect): Queries can also join data across different Superset databases. - The dialect is built in top of the shillelagh library, leveraging SQLite to + The dialect is built in top of the Shillelagh library, leveraging SQLite to create virtual tables on-the-fly proxying Superset tables. The `SupersetShillelaghAdapter` adapter is responsible for returning data when a Superset table is accessed. @@ -164,11 +165,20 @@ class Duration(Field[datetime.timedelta, datetime.timedelta]): db_api_type = "DATETIME" +class Decimal(Field[decimal.Decimal, decimal.Decimal]): + """ + Shillelagh field used for representing decimals. + """ + + type = "DECIMAL" + db_api_type = "NUMBER" + + # pylint: disable=too-many-instance-attributes class SupersetShillelaghAdapter(Adapter): """ - A shillelagh adapter for Superset tables. + A Shillelagh adapter for Superset tables. Shillelagh adapters are responsible for fetching data from a given resource, allowing it to be represented as a virtual table in SQLite. This one works @@ -190,6 +200,7 @@ class SupersetShillelaghAdapter(Adapter): datetime.datetime: DateTime, datetime.time: Time, datetime.timedelta: Duration, + decimal.Decimal: Decimal, } @staticmethod From 757bff483a2aa67db90570e8ee4ab57176eb8771 Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Tue, 21 Nov 2023 10:23:19 -0500 Subject: [PATCH 2/2] Better fallback field --- superset/extensions/metadb.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/superset/extensions/metadb.py b/superset/extensions/metadb.py index 305ac86dd0a67..bdfe1ae1e7cbb 100644 --- a/superset/extensions/metadb.py +++ b/superset/extensions/metadb.py @@ -50,7 +50,6 @@ from shillelagh.backends.apsw.dialects.base import APSWDialect from shillelagh.exceptions import ProgrammingError from shillelagh.fields import ( - Blob, Boolean, Date, DateTime, @@ -174,6 +173,18 @@ class Decimal(Field[decimal.Decimal, decimal.Decimal]): db_api_type = "NUMBER" +class FallbackField(Field[Any, str]): + """ + Fallback field for unknown types; converts to string. + """ + + type = "TEXT" + db_api_type = "STRING" + + def parse(self, value: Any) -> str | None: + return value if value is None else str(value) + + # pylint: disable=too-many-instance-attributes class SupersetShillelaghAdapter(Adapter): @@ -279,7 +290,7 @@ def get_field(cls, python_type: Any) -> Field: """ Convert a Python type into a Shillelagh field. """ - class_ = cls.type_map.get(python_type, Blob) + class_ = cls.type_map.get(python_type, FallbackField) return class_(filters=[Equal, Range], order=Order.ANY, exact=True) def _set_columns(self) -> None: