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: IS NULL filter operator for numeric columns #13496

Merged
merged 9 commits into from
Mar 10, 2021
Merged

Conversation

ktmud
Copy link
Member

@ktmud ktmud commented Mar 6, 2021

SUMMARY

Fixes #13229 where filters for numeric columns could not use IS NULL and IS NOT NULL operators in SIMPLE mode.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Before

Snip20210305_30

After

filter-is-null-after

TEST PLAN

Manual testing

  • Will add more unit tests once SQL query generator was refactored and split into smaller testable functions

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

@ktmud ktmud added the need:tests This PR requires tests label Mar 6, 2021
@ktmud ktmud marked this pull request as ready for review March 8, 2021 06:13
const isString =
firstValue !== undefined && Number.isNaN(Number(firstValue));
const quote = isString ? "'" : '';
const [prefix, suffix] = isMulti ? ['(', ')'] : ['', ''];
const formattedComparators = comparatorArray.map(
val => `${quote}${isString ? val.replace("'", "''") : val}${quote}`,
val =>
`${quote}${isString ? String(val).replace("'", "''") : val}${quote}`,
Copy link
Member Author

Choose a reason for hiding this comment

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

This fixes a rare case when <NULL> is used as the first filter value for a numeric column, saving the filter will throw a JS error:

null-first

utils.FilterOperator.NOT_IN.value,
):
cond = col_obj.get_sqla_col().in_(eq)
if isinstance(eq, str) and NULL_STRING in eq:
Copy link
Member Author

Choose a reason for hiding this comment

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

NULL_STRING is already parsed to None in filter_values_handler, so this is not needed.

if eq:
cond = or_(is_null_cond, col_obj.get_sqla_col().in_(eq))
else:
cond = is_null_cond
Copy link
Member Author

Choose a reason for hiding this comment

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

Do additional check to make the generated where clause cleaner for when there are NULL in the IN list.

Previously it may generate:

WHERE abc in (NULL, 123) OR abc IS NULL

Now it generates:

WHERE abc in (123, ) OR abc IS NOT NULL

Copy link
Member

Choose a reason for hiding this comment

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

why NOT NULL in the last expression ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, it was a typo... Thanks for noting.

@codecov
Copy link

codecov bot commented Mar 8, 2021

Codecov Report

Merging #13496 (c7ad854) into master (9e964f4) will decrease coverage by 0.15%.
The diff coverage is 85.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #13496      +/-   ##
==========================================
- Coverage   77.66%   77.51%   -0.16%     
==========================================
  Files         902      902              
  Lines       45873    45873              
  Branches     5598     5596       -2     
==========================================
- Hits        35628    35558      -70     
- Misses      10111    10181      +70     
  Partials      134      134              
Flag Coverage Δ
cypress 57.44% <100.00%> (-0.02%) ⬇️
hive ?
javascript 63.58% <100.00%> (-0.01%) ⬇️
mysql 80.45% <83.33%> (-0.01%) ⬇️
postgres 80.49% <83.33%> (-0.01%) ⬇️
presto 80.15% <83.33%> (-0.01%) ⬇️
python 80.71% <83.33%> (-0.28%) ⬇️
sqlite 80.11% <83.33%> (-0.01%) ⬇️

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

Impacted Files Coverage Δ
superset/connectors/sqla/models.py 90.66% <82.35%> (-0.32%) ⬇️
superset-frontend/src/explore/exploreUtils.js 69.81% <100.00%> (-0.75%) ⬇️
superset/connectors/base/models.py 90.78% <100.00%> (+0.28%) ⬆️
superset/db_engines/hive.py 0.00% <0.00%> (-85.72%) ⬇️
superset/db_engine_specs/hive.py 74.23% <0.00%> (-16.54%) ⬇️
...ponents/nativeFilters/FilterBar/CascadePopover.tsx 95.77% <0.00%> (-1.41%) ⬇️

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 9e964f4...fbd06e8. Read the comment docs.

values = values[0]
else:
values = None
values = values[0] if values else None
Copy link
Member

Choose a reason for hiding this comment

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

if values could be dangerous, as [],0, None would return false, it would be nice to be a bit more specific in the check.

cond,
col_obj.get_sqla_col() # pylint: disable=singleton-comparison
== None,
if is_list_target:
Copy link
Member

Choose a reason for hiding this comment

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

is it possible to add unit tests here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

More granular logics could be handled by actual unit tests when we break down the query generator. I also added "revisit:add-tests" label to mark this as a followup item.

if eq:
cond = or_(is_null_cond, col_obj.get_sqla_col().in_(eq))
else:
cond = is_null_cond
Copy link
Member

Choose a reason for hiding this comment

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

why NOT NULL in the last expression ?

@bkyryliuk
Copy link
Member

Thanks for the fix!

@ktmud ktmud merged commit b9884fb into apache:master Mar 10, 2021
@ktmud ktmud deleted the is-not-null branch March 10, 2021 18:15
serenajiang pushed a commit to airbnb/superset-fork that referenced this pull request Mar 10, 2021
allanco91 pushed a commit to allanco91/superset that referenced this pull request May 21, 2021
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 1.2.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 need:tests This PR requires tests size/M 🚢 1.2.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Table Viz errors with filters containing number column "IS NOT NULL" or "IS NULL"
3 participants