Bug description
When encountering the error sqlalchemy.exc.ArgumentError: Query has only expression-based entities, which do not apply to relationship property "SqlaTable.database" in Superset after logging in, and given that the SQLAlchemy version is 1.4.0, the issue typically arises from a mismatch between the expected model entities and the actual expression-based entities used in the query. This can happen when the ORM is expecting instances of mapped classes but receives SQL expressions instead, which are not compatible with relationship properties defined in the models.
How to reproduce the bug
- login
Screenshots/recordings
Superset version
master / latest-dev
Python version
3.9
Node version
Not applicable
Browser
Chrome
Additional context
SQLAlchemy 1.4.0 SQLAlchemy-Utils 0.38.3 Flask-SQLAlchemy 2.5.0 clickhouse-sqlalchemy 0.2.0
Checklist
- [X] I have searched Superset docs and Slack and didn't find a solution to my problem.
- [X] I have searched the GitHub issue tracker and didn't find a similar bug report.
- [X] I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.
Comment From: dosubot[bot]
@shuailingyi Hello there! I'm here to help you with any bugs, questions, or becoming a contributor. Let's squash those bugs together! 🤖
To resolve the sqlalchemy.exc.ArgumentError
related to the "Dashboard.changed_by" relationship property when logging into Superset, ensure that the changed_by
property is correctly defined in the Dashboard
class. The changed_by
property should be defined as a relationship to the User
model.
Here is the relevant code snippet from the Dashboard
class in superset/models/dashboard.py
:
class Dashboard(AuditMixinNullable, ImportExportMixin, Model):
"""The dashboard object!"""
__tablename__ = "dashboards"
id = Column(Integer, primary_key=True)
dashboard_title = Column(String(500))
position_json = Column(utils.MediumText())
description = Column(Text)
css = Column(utils.MediumText())
certified_by = Column(Text)
certification_details = Column(Text)
json_metadata = Column(utils.MediumText())
slug = Column(String(255), unique=True)
slices: list[Slice] = relationship(
Slice, secondary=dashboard_slices, backref="dashboards"
)
owners = relationship(
security_manager.user_model,
secondary=dashboard_user,
passive_deletes=True,
)
tags = relationship(
"Tag",
overlaps="objects,tag,tags",
secondary="tagged_object",
primaryjoin="and_(Dashboard.id == TaggedObject.object_id, "
"TaggedObject.object_type == 'dashboard')",
secondaryjoin="TaggedObject.tag_id == Tag.id",
viewonly=True, # cascading deletion already handled by superset.tags.models.ObjectUpdater.after_delete
)
published = Column(Boolean, default=False)
is_managed_externally = Column(Boolean, nullable=False, default=False)
external_url = Column(Text, nullable=True)
roles = relationship(security_manager.role_model, secondary=DashboardRoles)
embedded = relationship(
"EmbeddedDashboard",
back_populates="dashboard",
cascade="all, delete-orphan",
)
export_fields = [
"dashboard_title",
"position_json",
"json_metadata",
"description",
"css",
"slug",
"certified_by",
"certification_details",
"published",
]
extra_import_fields = ["is_managed_externally", "external_url"]
@property
def changed_by_name(self) -> str:
if not self.changed_by:
return ""
return str(self.changed_by)
Ensure that the changed_by
property is correctly defined and linked to the User
model. If the changed_by
property is missing or incorrectly defined, it can cause the sqlalchemy.exc.ArgumentError
[1].
To continue talking to Dosu, mention @dosu.
Comment From: rusackas
This has been open/untouched for quite some time, and I'm tempted to close it as stale/inactionable. Can you give us some more reproduction steps besides "login" to go on? Also curious if you're still facing this in 4.1.1 or at all, since there have been a lot of SQL parsing updates made.
Comment From: rusackas
We've replaced SQLParse with SQLGlot, and that may have some impact here. Otherwise closeing here for lack of reproduction steps, but happy to revisit if/when needed.