Open ishirvani opened 2 months ago
Hey there, @ishirvani! I'm here to help you with any bugs, questions, or contributions you have. Let's tackle this together! 😊
I found a similar unsolved discussion regarding the integration of SQL Server Analysis Services (SSAS) with Apache Superset. You can check it out here: Add Support for SQL Server Analysis Services (SSAS) Connection with MDX Query Execution, Dimension Management, Pivot Tables, and Domain User Login [1].
To enhance Apache Superset to support SSAS with features like MDX query execution, dimension and database management, pivot table functionalities, and domain user login, you would need to create a new DB engine spec for SSAS. Here is a high-level approach:
Create a new DB engine spec for SSAS:
superset/db_engine_specs
directory, for example, superset/db_engine_specs/ssas.py
.BaseEngineSpec
class to handle SSAS-specific functionalities.MDX Query Execution:
execute
method to support MDX queries.Dimension and Database Management:
Pivot Table Functionalities:
Domain User Login:
Here is a simplified example of what the new DB engine spec might look like:
# superset/db_engine_specs/ssas.py
from superset.db_engine_specs.base import BaseEngineSpec
class SSASEngineSpec(BaseEngineSpec):
engine = 'ssas'
engine_name = 'SQL Server Analysis Services'
@classmethod
def execute(cls, cursor, query, **kwargs):
# Implement MDX query execution logic
cursor.execute(query)
return cursor.fetchall()
@classmethod
def get_dimensions(cls, cursor):
# Implement logic to fetch dimensions
cursor.execute("SELECT * FROM $system.DISCOVER_DIMENSIONS")
return cursor.fetchall()
@classmethod
def get_databases(cls, cursor):
# Implement logic to fetch databases
cursor.execute("SELECT * FROM $system.DISCOVER_CATALOGS")
return cursor.fetchall()
# Add more methods as needed to support other functionalities
# superset/config.py
from superset.db_engine_specs.ssas import SSASEngineSpec
DATABASES = {
'ssas': SSASEngineSpec,
# other database specs
}
For domain user login, you can configure LDAP authentication in the superset_config.py
file:
# When using LDAP Auth, setup the LDAP server
AUTH_LDAP_SERVER = "ldap://ldapserver.new"
This is a simplified example, and the actual implementation would require more detailed handling of SSAS-specific features and integration points [2][3][4].
To continue talking to Dosu, mention @dosu.
Hello,
I am working on adding support for SQL Server Analysis Services (SSAS) to Apache Superset, with the goal of connecting via domain user authentication and ensuring that once connected, the user can view the full set of data, including databases and dimensions.
Here’s what I’ve done so far:
Creating a new DB engine spec: I’ve implemented an initial version of a custom engine spec for SSAS that includes MDX query execution and fetching metadata like dimensions and databases. Here’s the implementation I’ve started with:
python Copy code from superset.db_engine_specs.base import BaseEngineSpec
class SSASEngineSpec(BaseEngineSpec): engine = 'ssas' engine_name = 'SQL Server Analysis Services'
@classmethod
def execute(cls, cursor, query, **kwargs):
cursor.execute(query)
return cursor.fetchall()
@classmethod
def get_dimensions(cls, cursor):
cursor.execute("SELECT * FROM $system.DISCOVER_DIMENSIONS")
return cursor.fetchall()
@classmethod
def get_databases(cls, cursor):
cursor.execute("SELECT * FROM $system.DISCOVER_CATALOGS")
return cursor.fetchall()
Integrating domain user authentication: My goal is to connect to SSAS using domain user credentials (via Kerberos or LDAP). I want to ensure that once the domain user is authenticated, they can view the entire dataset (databases and dimensions) available in SSAS.
Testing and displaying data: After the successful connection, the user should be able to explore the SSAS databases and dimensions through Superset's interface, including using MDX queries.
I would like some guidance on:
How to correctly configure the SSAS connection in Superset for domain user authentication, ensuring that it works with Kerberos or LDAP. Best practices or additional steps to fully register and make this SSAS connection selectable and usable for users. How to ensure that, upon successful authentication, the entire SSAS data (including all databases and dimensions) is properly displayed to the user within Superset. Any insights or existing implementations around SSAS in Superset, specifically for domain user logins, would be greatly appreciated!
Thank you for your support.
To correctly configure the SSAS connection in Apache Superset for domain user authentication using Kerberos or LDAP, and ensure the connection is fully registered and usable, follow these steps:
Ensure you have the necessary driver for SSAS. Since SSAS is not explicitly listed, you may need to find a compatible SQLAlchemy dialect and Python driver for SSAS.
In the Secure Extra
field of the database connection configuration, add the following JSON configuration for Kerberos authentication:
{
"auth_method": "kerberos",
"auth_params": {
"service_name": "superset",
"config": "/path/to/krb5.config"
}
}
Ensure you have the trino[kerberos]
or trino[all]
package installed:
pip install trino[kerberos]
If you prefer LDAP, you will need to configure it similarly in the Secure Extra
field. However, specific details for LDAP configuration are not provided in the given context.
After configuring the authentication, register the connection through the Superset web UI:
Secure Extra
field.Once the connection is successfully tested and saved, Superset should be able to display all databases and dimensions available in SSAS to the authenticated user.
Secure Extra
Field{
"auth_method": "kerberos",
"auth_params": {
"service_name": "superset",
"config": "/path/to/krb5.config"
}
}
Ensure the connection string and other parameters are correctly set according to the SSAS driver documentation [1].
Your custom DB engine spec for SSAS looks good. Ensure you have implemented the necessary methods and attributes to support metadata fetching and query execution. Here are some key methods and attributes you might need:
fetch_metadata
: Fetch metadata from the database.execute
: Execute SQL queries against the database.get_dimensions
: Fetch dimensions from SSAS.get_databases
: Fetch databases from SSAS.engine
: Specifies the engine type.engine_name
: Specifies the engine name.from superset.db_engine_specs.base import BaseEngineSpec
class SSASEngineSpec(BaseEngineSpec):
engine = 'ssas'
engine_name = 'SQL Server Analysis Services'
@classmethod
def execute(cls, cursor, query, **kwargs):
cursor.execute(query)
return cursor.fetchall()
@classmethod
def get_dimensions(cls, cursor):
cursor.execute("SELECT * FROM $system.DISCOVER_DIMENSIONS")
return cursor.fetchall()
@classmethod
def get_databases(cls, cursor):
cursor.execute("SELECT * FROM $system.DISCOVER_CATALOGS")
return cursor.fetchall()
Add the new engine spec to the list of supported engines in Superset:
# superset/config.py
from superset.db_engine_specs.ssas import SSASEngineSpec
DATABASES = {
'ssas': SSASEngineSpec,
# other database specs
}
By following these steps, you should be able to configure the SSAS connection in Superset for domain user authentication, register the connection, and display the entire SSAS data to the user upon successful authentication [1][2].
To continue talking to Dosu, mention @dosu.
Here's the final version with a request for community help at the end:
Title: Issue with loading SSASEngineSpec - "Could not load database driver: SSASEngineSpec"
Hi Apache Superset team,
I am working on adding support for SQL Server Analysis Services (SSAS) to Superset. I have implemented a new class called SSASEngineSpec
as needed, but I am encountering the following error:
ERROR: Could not load database driver: SSASEngineSpec
from typing import Any, Optional
from datetime import datetime
from superset.db_engine_specs.base import BaseEngineSpec
class SSASEngineSpec(BaseEngineSpec):
engine = "ssas"
engine_name = "SQL Server Analysis Services"
@classmethod
def execute(cls, cursor: Any, query: str, **kwargs: Any) -> Any:
cursor.execute(query)
return cursor.fetchall()
@classmethod
def get_dimensions(cls, cursor: Any) -> list[tuple[Any, ...]]:
cursor.execute("SELECT * FROM $system.DISCOVER_DIMENSIONS")
return cursor.fetchall()
@classmethod
def get_databases(cls, cursor: Any) -> list[tuple[Any, ...]]:
cursor.execute("SELECT * FROM $system.DISCOVER_CATALOGS")
return cursor.fetchall()
@classmethod
def convert_dttm(cls, target_type: str, dttm: datetime) -> Optional[str]:
return f"'{dttm.isoformat()}'"
@classmethod
def fetch_data(cls, cursor: Any, limit: Optional[int] = None) -> list[tuple[Any, ...]]:
if not cursor.description:
return []
return super().fetch_data(cursor, limit)
superset_config.py
or similar) to load this new driver correctly?Additionally, I am trying to connect to SSAS using the following connection string format:
ssas://ip/ssas_dbname
Does this format look correct for SSAS connections in Superset?
I would greatly appreciate any guidance or documentation on resolving this error.
If anyone in the community has experience integrating SSAS with Superset, your input would be incredibly valuable. Any code samples, documentation, or suggestions to help resolve this issue would benefit not just me, but other developers looking to add SSAS support to Superset as well.
Thank you for your time and assistance!
To resolve the "Could not load database driver: SSASEngineSpec" error when adding support for SQL Server Analysis Services (SSAS) to Apache Superset, ensure that the SSASEngineSpec
is correctly registered and loaded. Here are the steps and configuration changes required:
Ensure that you have a class SSASEngineSpec
that extends BaseEngineSpec
and is properly defined in a module.
Make sure that the SSASEngineSpec
is included in the list of engine specs that Superset loads. This is done in the load_engine_specs
function.
# superset/db_engine_specs/ssas.py
from typing import Any, Optional
from datetime import datetime
from superset.db_engine_specs.base import BaseEngineSpec
class SSASEngineSpec(BaseEngineSpec):
engine = "ssas"
engine_name = "SQL Server Analysis Services"
@classmethod
def execute(cls, cursor: Any, query: str, **kwargs: Any) -> Any:
cursor.execute(query)
return cursor.fetchall()
@classmethod
def get_dimensions(cls, cursor: Any) -> list[tuple[Any, ...]]:
cursor.execute("SELECT * FROM $system.DISCOVER_DIMENSIONS")
return cursor.fetchall()
@classmethod
def get_databases(cls, cursor: Any) -> list[tuple[Any, ...]]:
cursor.execute("SELECT * FROM $system.DISCOVER_CATALOGS")
return cursor.fetchall()
@classmethod
def convert_dttm(cls, target_type: str, dttm: datetime) -> Optional[str]:
return f"'{dttm.isoformat()}'"
@classmethod
def fetch_data(cls, cursor: Any, limit: Optional[int] = None) -> list[tuple[Any, ...]]:
if not cursor.description:
return []
return super().fetch_data(cursor, limit)
Ensure the SSASEngineSpec
is loaded in superset/db_engine_specs/__init__.py
:
# superset/db_engine_specs/__init__.py
from pathlib import Path
import pkgutil
from importlib import import_module
from superset.db_engine_specs.base import BaseEngineSpec
def load_engine_specs() -> list[type[BaseEngineSpec]]:
engine_specs: list[type[BaseEngineSpec]] = []
# Load standard engines
db_engine_spec_dir = str(Path(__file__).parent)
for module_info in pkgutil.iter_modules([db_engine_spec_dir], prefix="."):
module = import_module(module_info.name, package=__name__)
engine_specs.extend(
getattr(module, attr)
for attr in module.__dict__
if is_engine_spec(getattr(module, attr))
)
# Manually add SSASEngineSpec if not using entry points
from superset.db_engine_specs.ssas import SSASEngineSpec
engine_specs.append(SSASEngineSpec)
# Load additional engines from external modules
for ep in entry_points(group="superset.db_engine_specs"):
try:
engine_spec = ep.load()
except Exception: # pylint: disable=broad-except
logger.warning("Unable to load Superset DB engine spec: %s", ep.name)
continue
engine_specs.append(engine_spec)
return engine_specs
The connection string format for SSAS should be verified against the specific driver you are using. A common format might look like:
ssas://username:password@hostname/ssas_dbname
Ensure that the driver you are using supports this format and that all necessary parameters are included.
By ensuring that the SSASEngineSpec
class is defined and properly registered in the load_engine_specs
function, you should be able to resolve the "Could not load database driver: SSASEngineSpec" error [1].
To continue talking to Dosu, mention @dosu.
Title: "Could not load database driver: SSASEngineSpec" after defining and registering custom engine for SSAS
Body: Hi,
I am facing an issue with adding support for SQL Server Analysis Services (SSAS) to Apache Superset. Despite following the necessary steps to define and register the SSASEngineSpec
class, I am encountering the following error:
Error:
Could not load database driver: SSASEngineSpec
Defined the SSASEngineSpec Class:
SSASEngineSpec
class in superset/db_engine_specs/ssas.py
, extending BaseEngineSpec
with methods for executing MDX queries and managing dimensions and databases.Registered SSASEngineSpec:
superset/db_engine_specs/__init__.py
to include SSASEngineSpec
in the list of engine specs in the load_engine_specs()
function.Connection String:
ssas://username:password@hostname/ssas_dbname
.Here are some relevant log entries when attempting to test the connection:
superset_app | 2024-09-14 08:36:08,301:DEBUG:superset.stats_logger:[stats_logger] (incr) test_connection_attempt
superset_app | 2024-09-14 08:36:08,319:DEBUG:superset.stats_logger:[stats_logger] (incr) test_connection_error.NoSuchModuleError
superset_app | 2024-09-14 08:36:08,322:DEBUG:superset.stats_logger:[stats_logger] (incr) DatabaseRestApi.test_connection.warning
superset_app | 2024-09-14 08:36:08,322:WARNING:superset.views.error_handling:CommandException
superset_app | Traceback (most recent call last):
superset_app | File "/app/superset/commands/database/test_connection.py", line 143, in run
superset_app | with database.get_sqla_engine(override_ssh_tunnel=ssh_tunnel) as engine:
superset_app | File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__
superset_app | return next(self.gen)
superset_app | File "/app/superset/models/core.py", line 446, in get_sqla_engine
superset_app | yield self._get_sqla_engine(
superset_app | File "/app/superset/models/core.py", line 465, in _get_sqla_engine
superset_app | self.db_engine_spec.validate_database_uri(sqlalchemy_url)
superset_app | File "/app/superset/db_engine_specs/base.py", line 2249, in validate_database_uri
superset_app | sqlalchemy_uri.get_driver_name(), set()
superset_app | File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/url.py", line 625, in get_driver_name
superset_app | return self.get_dialect().driver
superset_app | File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/url.py", line 680, in get_dialect
superset_app | entrypoint = self._get_entrypoint()
superset_app | File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/url.py", line 662, in _get_entrypoint
superset_app | cls = registry.load(name)
superset_app | File "/usr/local/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 343, in load
superset_app | raise exc.NoSuchModuleError(
superset_app | sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:ssas
superset_app |
superset_app | The above exception was the direct cause of the following exception:
superset_app |
superset_app | Traceback (most recent call last):
superset_app | File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 1484, in full_dispatch_request
superset_app | rv = self.dispatch_request()
superset_app | File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 1469, in dispatch_request
superset_app | return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
superset_app | File "/usr/local/lib/python3.10/site-packages/flask_appbuilder/security/decorators.py", line 95, in wraps
superset_app | return f(self, *args, **kwargs)
superset_app | File "/app/superset/views/base_api.py", line 119, in wraps
superset_app | duration, response = time_function(f, self, *args, **kwargs)
superset_app | File "/app/superset/utils/core.py", line 1364, in time_function
superset_app | response = func(*args, **kwargs)
superset_app | File "/app/superset/utils/log.py", line 303, in wrapper
superset_app | value = f(*args, **kwargs)
superset_app | File "/app/superset/views/base_api.py", line 91, in wraps
superset_app | return f(self, *args, **kwargs)
superset_app | File "/app/superset/databases/api.py", line 1219, in test_connection
superset_app | TestConnectionDatabaseCommand(item).run()
superset_app | File "/app/superset/commands/database/test_connection.py", line 193, in run
superset_app | raise DatabaseTestConnectionDriverError(
superset_app | superset.commands.database.exceptions.DatabaseTestConnectionDriverError: Could not load database driver: SSASEngineSpec
superset_app | 2024-09-14 08:36:08,329:INFO:werkzeug:172.18.0.1 - - [14/Sep/2024 08:36:08] "POST /api/v1/database/test_connection/ HTTP/1.1" 422 -
I have confirmed that SSASEngineSpec
is defined and registered according to the steps outlined in the documentation. However, the error persists. Could you provide any additional guidance or check if there might be something missed in the configuration or implementation? Any assistance would be greatly appreciated.
Thank you!
Apache Superset currently lacks native support for SQL Server Analysis Services (SSAS), a popular OLAP (Online Analytical Processing) platform. Integrating SSAS into Superset with support for MDX (Multidimensional Expressions) queries, dimension and database management, pivot table functionalities, and domain user login would greatly enhance its analytical capabilities.
Motivation
Adding these features to Superset will provide several benefits:
Proposed Solution
Connection Support:
MDX Query Execution:
Dimension and Database Management:
Pivot Table Functionality:
Domain User Login:
Documentation and User Guide:
Testing:
Additional Context
Steps to Implement
Thank you for considering this feature request. Implementing these enhancements will provide significant value to users who depend on SSAS for their business intelligence needs and wish to leverage Apache Superset for advanced analytics.
iman shirvani
Originally posted by @ishirvani in https://github.com/apache/superset/discussions/30182