Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dataset): fetch metadata on dataset creation may raise broad exceptions #11973

Merged
merged 6 commits into from
Dec 11, 2020

Conversation

dpgaspar
Copy link
Member

@dpgaspar dpgaspar commented Dec 9, 2020

SUMMARY

fetch_metadata may raise broad exceptions from database drivers, the try/catch block was too narrow

Example pydruid can raise when a column type is not supported:

pydruid.db.exceptions.NotSupportedError: Type BLOB is not supported

ADDITIONAL INFORMATION

  • Has associated issue:
  • Changes UI
  • Requires DB Migration.
  • Confirm DB Migration upgrade and downgrade tested.
  • Introduces new feature or API
  • Removes existing feature or API

@codecov-io
Copy link

codecov-io commented Dec 9, 2020

Codecov Report

Merging #11973 (82e9ab0) into master (cc44a2c) will decrease coverage by 5.97%.
The diff coverage is 0.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #11973      +/-   ##
==========================================
- Coverage   66.26%   60.29%   -5.98%     
==========================================
  Files         941      897      -44     
  Lines       45715    43912    -1803     
  Branches     4395     3889     -506     
==========================================
- Hits        30293    26475    -3818     
- Misses      15287    17437    +2150     
+ Partials      135        0     -135     
Flag Coverage Δ
cypress 54.43% <ø> (+10.62%) ⬆️
javascript ?
python 63.39% <0.00%> (-0.87%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
superset/connectors/sqla/models.py 90.36% <0.00%> (-0.42%) ⬇️
...uperset-frontend/src/dashboard/util/dnd-reorder.js 0.00% <0.00%> (-100.00%) ⬇️
...rset-frontend/src/dashboard/util/getEmptyLayout.js 0.00% <0.00%> (-100.00%) ⬇️
...dashboard/components/resizable/ResizableHandle.jsx 0.00% <0.00%> (-100.00%) ⬇️
.../src/dashboard/util/getFilterScopeFromNodesTree.js 0.00% <0.00%> (-93.48%) ⬇️
...src/dashboard/components/gridComponents/Header.jsx 10.52% <0.00%> (-86.85%) ⬇️
...rc/dashboard/components/gridComponents/Divider.jsx 13.33% <0.00%> (-86.67%) ⬇️
...ontend/src/dashboard/util/getDashboardFilterKey.ts 14.28% <0.00%> (-85.72%) ⬇️
...end/src/SqlLab/components/ExploreResultsButton.jsx 8.00% <0.00%> (-84.00%) ⬇️
...nd/src/views/CRUD/data/query/QueryPreviewModal.tsx 14.70% <0.00%> (-82.97%) ⬇️
... and 398 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update cc44a2c...82e9ab0. Read the comment docs.

Copy link
Member

@villebro villebro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels pretty harsh to catch Exception, I wonder if there is some slightly more specific exception (or small set of exceptions) that could be used to catch the majority of these. Another option could be adding db specific exceptions to the db engine spec and then checking for those. Something like

def get_dbapi_exceptions(): Tuple[Exception, ...]:
    from pydruid import CustomPydryidException
    return (CustomPydryidException, )

@dpgaspar
Copy link
Member Author

dpgaspar commented Dec 9, 2020

It feels pretty harsh to catch Exception, I wonder if there is some slightly more specific exception (or small set of exceptions) that could be used to catch the majority of these. Another option could be adding db specific exceptions to the db engine spec and then checking for those. Something like

def get_dbapi_exceptions(): Tuple[Exception, ...]:
    from pydruid import CustomPydryidException
    return (CustomPydryidException, )

I really don't like introducing broad exceptions, but dbapi exception's are raising custom exceptions from Exception. Yet created this related PR on pydruid to set SQLAlchemy visit_* methods raise from CompileError: druid-io/pydruid#243
I think is what we should expect here. But other drivers will raise childs of Exception.
Introducing all these imports inside superset will increase complexity and maintainability, IMO better to live with the broad except

@pull-request-size pull-request-size bot added size/S and removed size/M labels Dec 9, 2020
Copy link
Member

@betodealmeida betodealmeida left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I'm taking a look at pydruid and trying to repro the problem and see what needs to be done to support BLOBs.

@john-bodley
Copy link
Member

I thought SQLAlchemy should have the mechanism to catch all DB-API exceptions. Here is the SQLAlchemy wrapping of the NotSupportedError which is a child of sqlalchemy.exc.DatabaseError which is a child of sqlalchemy.exc.DBAPIError which eventually rolls up to a sqlalchemy.exc.SQLAlchemyError exception.

Either DBAPIError or SQLAlchemyError seems like a better candidate that Exception for broad SQLAlchemy issues.

@dpgaspar
Copy link
Member Author

dpgaspar commented Dec 9, 2020

I thought SQLAlchemy should have the mechanism to catch all DB-API exceptions. Here is the SQLAlchemy wrapping of the NotSupportedError which is a child of sqlalchemy.exc.DatabaseError which is a child of sqlalchemy.exc.DBAPIError which eventually rolls up to a sqlalchemy.exc.SQLAlchemyError exception.

Either DBAPIError or SQLAlchemyError seems like a better candidate that Exception for broad SQLAlchemy issues.

True, I was following the logic directly on pydruid: https://github.com/druid-io/pydruid/blob/master/pydruid/db/exceptions.py#L37

That ends up on Exception, SQLAlchemy wraps db-api exceptions, but this one was slipping and ended up being a 500 on the API. Will test it further

@betodealmeida
Copy link
Member

FIY, I fixed the BLOB issuse in pydruid here: druid-io/pydruid#244

@dpgaspar
Copy link
Member Author

dpgaspar commented Dec 9, 2020

Thats awesome @betodealmeida I think this approach here still makes sense since other drivers may raise on unsupported types. I'll double check if the exception is narrowed by SQLAlchemy or if we have to content with a broad exception

@dpgaspar
Copy link
Member Author

dpgaspar commented Dec 10, 2020

@john-bodley unfortunately these exceptions from sqlalchemy dialects (at SQL compile) do not raise any SQLAlchemy exception and SQLAlchemy does not wrap these up. Used elasticsearch-dbapi that follows the same exception pattern has pydruid and done an inpect MRO on the exception on our external_metadata method:

                except Exception as ex:  # pylint: disable=broad-except
                    import inspect
                    print(f"{inspect.getmro(ex.__class__)}")
                    col["type"] = "UNKNOWN"

The output:

(<class 'es.exceptions.NotSupportedError'>,
 <class 'es.exceptions.DatabaseError'>,
 <class 'es.exceptions.Error'>,
 <class 'Exception'>, <class 'BaseException'>, <class 'object'>
)

So it seems that we are bound to catching whatever exceptions the dialects may raise

@dpgaspar dpgaspar merged commit 916f7e9 into apache:master Dec 11, 2020
@dpgaspar dpgaspar deleted the fix/dataset-add branch December 11, 2020 11:07
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 1.0.0 labels Mar 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels size/XS 🚢 1.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants