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

  1. login

Screenshots/recordings

dash slice sqltable

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.