Skip to content

sql compatible three-valued logic native filters #15058

Merged
clintropolis merged 21 commits into
apache:masterfrom
clintropolis:sql-compatible-native-tri-state-filtering
Oct 12, 2023
Merged

sql compatible three-valued logic native filters #15058
clintropolis merged 21 commits into
apache:masterfrom
clintropolis:sql-compatible-native-tri-state-filtering

Conversation

@clintropolis

@clintropolis clintropolis commented Sep 29, 2023

Copy link
Copy Markdown
Member

Description

This PR modifies Druid native filters to correctly observe SQL three-valued logic (true, false, unknown) instead of Druids classic two-state logic, with a new druid.generic.useThreeValueLogicForNativeFilters which defaults to true and also druid.expressions.useStrictBooleans is set to true and druid.generic.useDefaultValueForNull is false (both the defaults in upcoming Druid 28, see #14154).

The most prominent example of what is fixed by this is something like the following query

Screenshot 2023-09-07 at 8 30 52 PM

which prior to this change would incorrect match null values, but after behaves in SQL compliant fashion and only matches actual values:

Screenshot 2023-09-07 at 8 29 46 PM

This change has only been done in SQL compatible/strict boolean mode to be consistent with the behavior of Druids native expressions, which already using the correct tri-state logic system if these flags were in place.

Design

The design is pretty-straightforward, involves modifying the 3 interfaces involved in Druid native filter matching, BitmapColumnIndex, ValueMatcher, and VectorValueMatcher, to accept an additional boolean includeUnknown argument when computing their matches.

public interface BitmapColumnIndex
{
  ...
  <T> T computeBitmapResult(BitmapResultFactory<T> bitmapResultFactory, boolean includeUnknown);
  ...
}
public interface ValueMatcher extends HotLoopCallee
{
  ...
  boolean matches(boolean includeUnknown);
  ...
}
public interface VectorValueMatcher extends VectorSizeInspector
{
  ...
  ReadableVectorMatch match(ReadableVectorMatch mask, boolean includeUnknown);
  ...
}

The idea is fairly simple, when includeUnknown is false, filters only consider rows matching when the match is definitely true, and when includeUnknown is true, the filters consider both definitely true and also 'unknown' values as matches. This primarily comes into play when a NotFilter is involved, during which we only want to match the values of a filter that are definitely false. So the NotFilter will flip the value of includeUnknown, delegating to the child filter what it actually considers 'unknown', to get matches for both TRUE and UNKNOWN, which it can then invert to translate into matches that are only `FALSE.

For example, the native equality filter, something like x = 'hello', with includeUnknown set to false will match all rows that have the value 'hello'. For something like x != 'hello', the NotFilter will call the match methods of the child equality filter with includeUnknown set to true, which will consider rows with 'hello' as matches, and also rows with NULL as matches, which the NotFilter can then flip to consider all of the rows with non-null values that are not equal to 'hello' as the matches.

Another example that handles includeUnknown differently (which is not actually present in this PR, but I am planning to add in a follow-up PR) would be something like a native "is true" filter. The "is true" filter considers non-null truthy values as matches regardless of the value of includeUnknown since it doesn't have any "unknown" values, the rows are either definitely true or definitely not true, so something like is not true the child filter would still only return the rows that match true, allowing the not filter to correctly match rows with both false and unknown values.

For predicate based filters, DruidPredicateFactory has a new method added,

  default boolean isNullInputUnknown()
  {
    return true;
  }

which is used to indicate if null inputs to the predicate should be considered as 'unknowns' and automatically match whenever 'includeUnknown' is set to true, or if they should be delegated to the predicate to have it directly match the value, since some predicates do in fact match null values (such as bloom filters, various expression filters, etc).

Rejected Designs

We primarily considered two other designs before moving forward with this one.

Separate unknown matching methods

One approach involved instead of adding an argument to these native matching interfaces to instead have additional methods to split out 'unknown' matching, e.g. adding a boolean unknown(); method to the ValueMatcher interface, and similar for index and vector matchers. In some ways, I actually still kind of prefer this approach because it is nice and tidy and unknown matching is handled completely separately from 'definitely true' matching, however in practice it had a pretty big downside, which is that the VectorValueMatcher implementations are effectively forced to maintain two vectors, one for the true selection and one for the unknown selection, or alternately iterate the vector twice if the unknowns are asked for, and also greatly increased the complexity of vector matcher implementations. We were also unable to think of any benefit to being able to keep the unknowns separated from the matches, so we went with the argument approach instead.

Simulate it in the SQL layer

This approach involved just making the SQL planner introduce the necessary extra native filters required to ensure correct behavior entirely in the SQL planner, and is basically sketched out in #14949. The idea is like for something like x != 'hello' we plan into a native and(not(eq(x, 'hello')), not(null(x)). There are some nice things about this approach, like not having to modify the native layer at all, but ultimately the downsides were worry that it could never be as performant as supporting this directly at the native layer, greatly increased complexity of the filter analysis step in the sql planner, the requirement to introduce a filter optimizer to remove duplicated filters added implicitly to map two to three valued logic, and lastly, the cognitive burden of the SQL layer having a different behavior than queries run directly at the native layer due to the filters which would be added implicitly at the SQL layer to produce correct behavior from the native layer.

Release note

Druid filtering now correctly observes SQL three-valued logic (true, false, unknown) instead of Druids classic two-state logic whenever druid.expressions.useStrictBooleans = true and druid.generic.useDefaultValueForNull = false. This will potentially change query results when these configuration values are set, particularly when NOT filters are involved, but for the better as queries should behave as one would expect when using SQL.


This PR has:

  • been self-reviewed.
  • added documentation for new or modified features or behaviors.
  • a release note entry in the PR description.
  • added Javadocs for most classes and all non-trivial methods. Linked related entities via Javadoc links.
  • added or updated version, license, or notice information in licenses.yaml
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added unit tests or modified existing tests to cover new code paths, ensuring the threshold for code coverage is met.
  • added integration tests.
  • been tested in a test Druid cluster.

…s.useStrictBooleans=true and druid.generic.useDefaultValueForNull=false
@github-actions github-actions Bot added Area - Documentation Area - Batch Ingestion Area - Segment Format and Ser/De Area - MSQ For multi stage queries - https://github.com/apache/druid/issues/12262 labels Sep 29, 2023
@clintropolis clintropolis changed the title sql compatible tri-state native logical filters sql compatible three-valued logic native filters Sep 29, 2023
@clintropolis clintropolis added this to the 28.0 milestone Oct 2, 2023
@clintropolis

Copy link
Copy Markdown
Member Author

coverage failure is related to sql compat mode = false, where almost none of this new code runs in that mode so i guess is expected, will poke around to see if there is anything i can do to make the bot happy though

return o -> stringPredicate.apply(null);
}

default boolean isNullInputUnknown()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Javadoc would be helpful

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

added

};
}

public static ValueMatcher makeAlwaysFalseMatcher(final DimensionSelector selector, boolean multiValue)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Javadoc would be helpful here, since it's unclear when to use this one vs allFalse

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

added javadocs and also to the constant allFalse/allTrue/allUnknown methods

* @param includeUnknown mapping for Druid native two state logic system into SQL three-state logic system. If set
* to true, this method should also return true if the result is 'unknown' to be a match, such
* as from the input being null valued. Used primarily to allow
* {@link org.apache.druid.segment.filter.NotFilter} to invert a match in an SQL compliant

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

tiniest of all nits: "a SQL" is better than "an SQL" because "SQL" is pronounced "sequel" 😉

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

lies

@Override
public boolean isNullInputUnknown()
{
return !values.contains(null);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cache this? Looks like isNullInputUnknown is called row-by-row in certain cases.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

probably a few others that would be useful to cache too, will try to fix them

// the list)
if (values.get(0) == null) {
return NullDimensionSelectorHolder.NULL_DIMENSION_SELECTOR;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is this needed — doesn't constant(null) do the same thing?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

oops i think it is not, i think i must have confused myself between the constant method which diverts nulls to the nil selector and the ConstantDimensionSelector which guards against nulls and explodes.

if (row.size() == 0) {
return true;
}
//noinspection SSBasedInspection

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the SSBasedInspection is complaining that row.size() is called for each iteration rather than being saved in a local variable. Might as well save it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

cool, i forgot where this was defined and couldn't remember why it warned against it, but that makes sense. looks like a few other places that can also be updated

public boolean matches()
public boolean matches(boolean includeUnknown)
{
// todo (clint): what to do about includeUnknown

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should avoid committing todos.

IMO, column comparison should ignore includeUnknown, i.e. if inputs are x and y it should be treated as x IS NOT DISTINCT FROM y. Just to keep things simple.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

cool, forgot about this todo, will add javadoc to this filter to call out this behavior.

}

final ReadableVectorMatch match = filterMatcher.match(VectorMatch.allTrue(baseOffset.getCurrentVectorSize()));
final ReadableVectorMatch match = filterMatcher.match(VectorMatch.allTrue(baseOffset.getCurrentVectorSize()),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Formatting is a little wonky

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

this is the main reason i hate using intellij to add parameters with default values for me using the refactor dialog thingo... on the one hand i'm lazy and its nice it can fill the falses in everywhere, but it always mangles everything so idk if i really come out ahead...

import java.util.Set;

/**
* Nice filter you have there... NOT!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good one

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@abhishekagarwal87 abhishekagarwal87 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I am only 20% done but I had some questions about the change is implemented before I proceed further. The PR description too, while explains the problem and the solution, didn't reveal much detail on implementation front.

Comment thread docs/querying/sql-data-types.md Outdated
if (o == null || o instanceof Object[]) {
if (includeUnknown && o == null && predicateFactory.isNullInputUnknown()) {
selection[numRows++] = rowNum;
} else if (o == null || o instanceof Object[]) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
} else if (o == null || o instanceof Object[]) {
} else if (o instanceof Object[]) {

shouldn't it be the above?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

the previous case was handling if includeUnknown and predicateFactory.isNullInputUnknown(). If predicateFactory.isNullInputUnknown() is false then we still have to evaluate the predicate against the value, including nulls, so we want to push nulls and arrays into the predicate directly so they don't get wrapped as a single element array like the else clause is doing

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

btw, updated the javadocs on isNullInputUnknown of the predicate factory to hopefully clear this up

@clintropolis

Copy link
Copy Markdown
Member Author

I am only 20% done but I had some questions about the change is implemented before I proceed further. The PR description too, while explains the problem and the solution, didn't reveal much detail on implementation front.

Updated the PR description to go over the design a bit with some examples, as well as discussing the other designs considered before settling on this one.

@abhishekagarwal87 abhishekagarwal87 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good to me, overall. I discussed with @clintropolis offline to understand the PR a bit more.

I think the includeUnknown and isNullInputUnknown could be better named for parity. E.g.
argument - includeUnknown
function name - doesNotIncludeUnknown()

or

argument - matchesUnknown
function name - doesNotMatchUnknown()

{
this.extractionFn = extractionFn;
this.values = values;
this.hasNull = !values.contains(null);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
this.hasNull = !values.contains(null);
this.hasNull = values.contains(null);

@Override
public boolean isNullInputUnknown()
{
return hasNull;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
return hasNull;
return !hasNull;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

oops yea, i named this bad, will flip it around

Comment on lines +98 to +114
if (includeUnknown) {
final int[] vector = selector.getRowVector();
final int[] inputSelection = mask.getSelection();
final int inputSelectionSize = mask.getSelectionSize();
final int[] outputSelection = match.getSelection();
int outputSelectionSize = 0;

for (int i = 0; i < inputSelectionSize; i++) {
final int rowNum = inputSelection[i];
if (NullHandling.isNullOrEquivalent(selector.lookupName(vector[rowNum]))) {
outputSelection[outputSelectionSize++] = rowNum;
}
}
match.setSelectionSize(outputSelectionSize);
return match;
}
return VectorMatch.allFalse();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would this cause any perf penalty for queries involving not filter?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yea, there will likely be some, but .. there isn't really anything we can do because the current behavior is incorrect. If the query results don't have to be correct then I'm sure we could make something even faster that doesn't read or check anything 😜

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

also in practice, strings and auto columns will be using indexes, which is just one extra bitmap operation to include the null bitmap in most cases, so in practice those should be not a lot different

public ConstantMultiValueDimensionSelector(List<String> values)
{
if (CollectionUtils.isNullOrEmpty(values)) {
throw new IllegalArgumentException("Use DimensionSelector.constant(null)");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I guess its a defensive check so druidException.defensive could be a better fit.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

ah yeah, updated this when i was adjacent to some code that was still throwing old exceptions, i can change if i push more commits

{
return BooleanValueMatcher.of(predicate.apply(null));
final Predicate<String> predicate = predicateFactory.makeStringPredicate();
return predicate.apply(null) ? ValueMatchers.allTrue() : ValueMatchers.allUnknown();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

shouldn't we be checking the value of predicateFactory.isNullInputUnknown() here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hmm, good question, I guess we technically should do ValueMatchers.allFalse if isNullInputUnknown is false and the predicate doesn't match null, will update and add test (if test agrees that is what should be happening)

@clintropolis

Copy link
Copy Markdown
Member Author

I think the includeUnknown and isNullInputUnknown could be better named for parity. E.g.
argument - includeUnknown
function name - doesNotIncludeUnknown()

i feel like doesNotIncludeUnknown doesn't really quite clearly convey the purpose of the method, which is "if includeUnknown is set, can we skip evaluating the predicate and just automatically return a match, or do we need to evaluate the predicate to determine if we match nulls."

or

argument - matchesUnknown
function name - doesNotMatchUnknown()

I went with includeUnknown to have a consistently named argument across all 3 interfaces that could be understandable in all 3 contexts; something like matchesUnknown seems sensible for value matchers but in the case of building indexes there isn't any existing match terminology in use, and so usually this parameter means 'include the null value bitmap'.

idk, naming is hard, hopefully the javadocs make it clear enough the intent of these arguments and functions

@clintropolis

Copy link
Copy Markdown
Member Author

The main change LGTM (other than the one notice), but in thinking about migrations, it occurs to me that people may have been accustomed to the old behavior of these filters, and would want a way to restore it without it being linked to druid.expressions.useStrictBooleans and druid.generic.useDefaultValueForNull. (Linking means people have no way to be, like, "I want Druid 27 behavior" once Druid 28 comes out.) I think that means we end up with a third parameter.

Added druid.generic.useThreeValueLogic as the 3rd parameter and updated docs to try to accurately describe the situation. All three of of these must be set for 3-value native filter logic (and all are by default), druid.generic.useDefaultValueForNull=false, druid.generic.useThreeValueLogic=true, and druid.expressions.useStrictBooleans=true.

I don't love it, but hopefully someday all of these can just go away and we only have "sql compatible Druid" and no other choice.

@clintropolis

Copy link
Copy Markdown
Member Author

added log messages to log.warn on cluster startup if non-recommended configurations are used:

2023-10-10T00:35:53,140 WARN [main] org.apache.druid.common.config.NullValueHandlingConfig - druid.generic.useDefaultValueForNull set to 'true', we recommend using 'false' if using SQL to query Druid for the most SQL compliant behavior, see https://druid.apache.org/docs/latest/querying/sql-data-types#null-values for details
2023-10-10T00:35:53,140 WARN [main] org.apache.druid.common.config.NullValueHandlingConfig - druid.generic.useThreeValueLogic set to 'false', we recommend using 'true' if using SQL to query Druid for the most SQL compliant behavior, see https://druid.apache.org/docs/latest/querying/sql-data-types#boolean-logic for details
2023-10-10T00:35:53,156 WARN [main] org.apache.druid.math.expr.ExpressionProcessingConfig - druid.expressions.useStrictBooleans set to 'false', we recommend using 'true' if using SQL to query Druid for the most SQL compliant behavior, see https://druid.apache.org/docs/latest/querying/sql-data-types#boolean-logic for details

Comment thread docs/configuration/index.md Outdated
|Property|Description|Default|
|---|---|---|
|`druid.generic.useDefaultValueForNull`|Set to `false` to store and query data in SQL compatible mode. When set to `true` (legacy mode), `null` values will be stored as `''` for string columns and `0` for numeric columns.|`false`|
|`druid.generic.useThreeValueLogic`|Set to `true` to use SQL compatible three-value logic when processing Druid filters when `druid.generic.useDefaultValueForNull` is `false` and `druid.expressions.useStrictBooleans` is `true`. When set to `false` Druid uses 2 value logic for filter processing, even when `druid.generic.useDefaultValueForNull=false` and `druid.expressions.useStrictBooleans` is true.|`true`|

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be druid.generic.useThreeValueLogicForNativeFilters? A mouthful, but isn't 3VL still used inside expressions when strict booleans is true and this is false?

Also, nit: consistency between "druid.generic.useDefaultValueForNull=false" vs "druid.expressions.useStrictBooleans is true"

Also, suggest linking to ../querying/sql-data-types.md for more info.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

changed

Comment thread docs/querying/sql-data-types.md Outdated
When `druid.expressions.useStrictBooleans = true`, Druid uses [three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic#SQL) for
[expressions](math-expr.md) evaluation, such as `expression` virtual columns or `expression` filters.
If `druid.generic.useDefaultValueForNull = false` (in combination with `druid.expressions.useStrictBooleans = true`), Druid also uses three-valued logic for native filters.
* [`druid.generic.useDefaultValueForNull`](../configuration/index.md#sql-compatible-null-handling) set to false (default), a runtime property which allows NULL values to exist in numeric columns and expressions, and string typed columns to distinguish between NULL and the empty string

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Clearer to replace "set to false" with "must be set to false"

(& similar comments for other bullets)


The [`druid.expressions.useStrictBooleans`](../configuration/index.md#expression-processing-configurations)
runtime property controls Druid's boolean logic mode. For the most SQL compliant behavior, set this to `true` (the default).
By default, Druid uses [SQL three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic#SQL) for filter processing

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hmm, we should add mention about this parameter to querying/filters.md too. This doc is all about SQL, but the same issue affects filters in native queries.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

add link to here from filters.md

@gianm gianm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, please fix up the doc grammar, although that can be done in a follow-up if you want to avoid another round of CI on this patch.

Comment thread docs/querying/filters.md Outdated
@gianm

gianm commented Oct 12, 2023

Copy link
Copy Markdown
Contributor

I notice there's just one CI failure right now, in code coverage for non-SQL-compat mode, where most of this new code wouldn't run. It's OK to ignore that one.

@clintropolis
clintropolis merged commit d0f6460 into apache:master Oct 12, 2023
@clintropolis
clintropolis deleted the sql-compatible-native-tri-state-filtering branch October 12, 2023 07:06
clintropolis added a commit to clintropolis/druid that referenced this pull request Oct 13, 2023
* sql compatible tri-state native logical filters when druid.expressions.useStrictBooleans=true and druid.generic.useDefaultValueForNull=false, and new druid.generic.useThreeValueLogicForNativeFilters=true
* log.warn if non-default configurations are used to guide operators towards SQL complaint behavior
LakshSingla pushed a commit that referenced this pull request Oct 15, 2023
* sql compatible tri-state native logical filters when druid.expressions.useStrictBooleans=true and druid.generic.useDefaultValueForNull=false, and new druid.generic.useThreeValueLogicForNativeFilters=true
* log.warn if non-default configurations are used to guide operators towards SQL complaint behavior
ektravel pushed a commit to ektravel/druid that referenced this pull request Oct 16, 2023
* sql compatible tri-state native logical filters when druid.expressions.useStrictBooleans=true and druid.generic.useDefaultValueForNull=false, and new druid.generic.useThreeValueLogicForNativeFilters=true
* log.warn if non-default configurations are used to guide operators towards SQL complaint behavior
clintropolis added a commit to clintropolis/druid that referenced this pull request Oct 17, 2023
changes:
* add IsTrueDimFilter, IsFalseDimFilter, and abstract IsBooleanDimFilter for native json filter implementations of `(filter) IS TRUE` and `(filter) IS FALSE`
* add IsBooleanFilter for actual filtering logic for these filters, which ignore includeUnknown to always use matches with false for true and !matches with true for false
* fix test incorrectly adjusted to wrong answer in apache#15058
clintropolis added a commit that referenced this pull request Oct 18, 2023
…5182)

* add native filters for "(filter) is true" and "(filter) is false"

changes:
* add IsTrueDimFilter, IsFalseDimFilter, and abstract IsBooleanDimFilter for native json filter implementations of `(filter) IS TRUE` and `(filter) IS FALSE`
* add IsBooleanFilter for actual filtering logic for these filters, which ignore includeUnknown to always use matches with false for true and !matches with true for false
* fix test incorrectly adjusted to wrong answer in #15058
* add tests for default value mode
clintropolis added a commit to clintropolis/druid that referenced this pull request Oct 18, 2023
…ache#15182)

* add native filters for "(filter) is true" and "(filter) is false"

changes:
* add IsTrueDimFilter, IsFalseDimFilter, and abstract IsBooleanDimFilter for native json filter implementations of `(filter) IS TRUE` and `(filter) IS FALSE`
* add IsBooleanFilter for actual filtering logic for these filters, which ignore includeUnknown to always use matches with false for true and !matches with true for false
* fix test incorrectly adjusted to wrong answer in apache#15058
* add tests for default value mode
LakshSingla pushed a commit that referenced this pull request Oct 19, 2023
…5182) (#15197)

* add native filters for "(filter) is true" and "(filter) is false"

changes:
* add IsTrueDimFilter, IsFalseDimFilter, and abstract IsBooleanDimFilter for native json filter implementations of `(filter) IS TRUE` and `(filter) IS FALSE`
* add IsBooleanFilter for actual filtering logic for these filters, which ignore includeUnknown to always use matches with false for true and !matches with true for false
* fix test incorrectly adjusted to wrong answer in #15058
* add tests for default value mode
CaseyPan pushed a commit to CaseyPan/druid that referenced this pull request Nov 17, 2023
* sql compatible tri-state native logical filters when druid.expressions.useStrictBooleans=true and druid.generic.useDefaultValueForNull=false, and new druid.generic.useThreeValueLogicForNativeFilters=true
* log.warn if non-default configurations are used to guide operators towards SQL complaint behavior
CaseyPan pushed a commit to CaseyPan/druid that referenced this pull request Nov 17, 2023
…ache#15182)

* add native filters for "(filter) is true" and "(filter) is false"

changes:
* add IsTrueDimFilter, IsFalseDimFilter, and abstract IsBooleanDimFilter for native json filter implementations of `(filter) IS TRUE` and `(filter) IS FALSE`
* add IsBooleanFilter for actual filtering logic for these filters, which ignore includeUnknown to always use matches with false for true and !matches with true for false
* fix test incorrectly adjusted to wrong answer in apache#15058
* add tests for default value mode
riovic918data pushed a commit to riovic918data/druid that referenced this pull request Jun 12, 2026
* sql compatible tri-state native logical filters when druid.expressions.useStrictBooleans=true and druid.generic.useDefaultValueForNull=false, and new druid.generic.useThreeValueLogicForNativeFilters=true
* log.warn if non-default configurations are used to guide operators towards SQL complaint behavior
riovic918data pushed a commit to riovic918data/druid that referenced this pull request Jun 12, 2026
…ache#15182)

* add native filters for "(filter) is true" and "(filter) is false"

changes:
* add IsTrueDimFilter, IsFalseDimFilter, and abstract IsBooleanDimFilter for native json filter implementations of `(filter) IS TRUE` and `(filter) IS FALSE`
* add IsBooleanFilter for actual filtering logic for these filters, which ignore includeUnknown to always use matches with false for true and !matches with true for false
* fix test incorrectly adjusted to wrong answer in apache#15058
* add tests for default value mode
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area - Batch Ingestion Area - Documentation Area - MSQ For multi stage queries - https://github.com/apache/druid/issues/12262 Area - Null Handling Area - Querying Area - Segment Format and Ser/De Area - SQL Design Review Release Notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants