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

Enable querying policy-enabled table in MSQ, and use RestrictedDataSource as a base in DataSourceAnalysis. #17666

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

cecemei
Copy link
Contributor

@cecemei cecemei commented Jan 25, 2025

Description

This PR enables querying policy-enabled table in MSQ.


Key changed/added classes in this PR
  • DataSourceAnalysis, getBaseTableDataSource can now return the base of RestrictedDataSource. This is a more robust solution than using the underlying table as base.
  • DruidQuery, can also be created by withPolicy, which just applies policy restriction to the original query.
  • MSQTaskQueryMaker would apply restrictions on DruidQuery, instead of throw permission error.
  • DataSourcePlan can handle RestrictedDataSource.
  • a new class RestrictedInputNumberDataSource, which basically wraps a NumberDataSource with a policy, and its SegmentMapFn can be used to create a RestrictedSegment.
  • RunWorkOrder, try to make a few refactors to make the code clear, no behavior change. ShufflePipelineBuilder.build(), it was not clear before that the channel future should only be returned when the resultFuture is ready. Also, the sanity check is moved to OutputChannels.
  • BaseLeafFrameProcessorFactory.makeProcessors(). Previously, makeSegmentMapFnProcessor can return null. After this PR, it cannot. The difference is that now the SegmentMapFn from query.dataSource is handled in ChainedProcessorManager for all query (was just join query before).

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.

@github-actions github-actions bot added Area - Batch Ingestion Area - Querying Area - MSQ For multi stage queries - https://github.com/apache/druid/issues/12262 labels Jan 25, 2025
@cecemei cecemei changed the title Enable RestrictedDataSource as a base in DataSourceAnalysis, and enab… Enable querying policy-enabled table in MSQ, and use RestrictedDataSource as a base in DataSourceAnalysis. Jan 25, 2025
@cecemei cecemei marked this pull request as ready for review January 28, 2025 04:08
Copy link
Member

@clintropolis clintropolis left a comment

Choose a reason for hiding this comment

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

had a first pass and have some questions and thoughts.

Also, maybe you could try to avoid reformatting entire files, all of these unrelated formatting changes make review harder than it should be. I know its just the tooling doing it to adhere to the style stuff, but my preference at least would be to do these cosmetic changes as you notice them as standalone PR to keep reviews simple.

*/
private <FactoryType extends FrameProcessorFactory<ProcessorReturnType, ManagerReturnType, ExtraInfoType>, ProcessorReturnType, ManagerReturnType, ExtraInfoType> void makeAndRunWorkProcessors()
throws IOException
private <FactoryT extends FrameProcessorFactory<ProcessorReturnT, ManagerReturnT, ExtraInfoT>, ProcessorReturnT, ManagerReturnT, ExtraInfoT>
Copy link
Member

Choose a reason for hiding this comment

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

nit: why change these names? just seems to add extra noise to the PR

Comment on lines +435 to +437
final int channelSize = outputChannels.getAllChannels().size();
final int parallelismBoundedByChannelSize = channelSize == 0 ? parallelism : Math.min(parallelism, channelSize);
final int maxOutstandingProcessors = Math.max(1, parallelismBoundedByChannelSize);
Copy link
Member

Choose a reason for hiding this comment

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

nit: the old code seemed clearer and had comments that were nice

workerToTaskIds.compute(i, (workerId, taskIds) -> {
if (taskIds == null) {
taskIds = new ArrayList<>();
}
taskIds.add(task.getId());
return taskIds;
});
workerToTaskIds.computeIfAbsent(i, (unused) -> (new ArrayList<>())).add(task.getId());
Copy link
Member

Choose a reason for hiding this comment

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

this isn't equivalent, previously it would always add the taskId to the worker, now it only adds if the worker isn't there, is that ok?

@@ -198,6 +198,7 @@ private Function<SegmentReference, SegmentReference> createSegmentMapFunction()

DataSource inlineChannelData(final DataSource originalDataSource)
{
// TODO: need to handle RestrictedInputNumberDataSource here
Copy link
Member

Choose a reason for hiding this comment

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

we typically don't leave TODO comments in the code, either do the thing or leave a bigger comment explaining the problem that needs addressed in the future

* join tree.
*/
@JsonTypeName("restrictedInputNumber")
public class RestrictedInputNumberDataSource implements DataSource
Copy link
Member

Choose a reason for hiding this comment

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

should this be InputNumberRestrictedDataSource instead?

Comment on lines +1004 to +1012
* Computes a native druid query, must be called from the constructor. The returned query will be one of following:
* <ul>
* <li> {@link GroupByQuery}
* <li> {@link WindowOperatorQuery}
* <li> {@link TimeBoundaryQuery}
* <li> {@link TimeseriesQuery}
* <li> {@link TopNQuery}
* <li> {@link ScanQuery}
* </ul>
Copy link
Member

Choose a reason for hiding this comment

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

nit: afaik we do not publish javadocs, so these could just be a plain list

/**
* Returns an updated {@link DruidQuery} based on the policy restrictions on tables.
*/
public DruidQuery withPolicies(Map<String, Optional<Policy>> policyMap)
Copy link
Member

Choose a reason for hiding this comment

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

this method seems off to me, like why isn't dataSource updated as well? I think calling this makes a DruidQuery that is in a bit of a strange state, and I think it basically only chill with the way that MSQTaskQueryMaker is working since it only really modifies the query part of the DruidQuery.

I'm not sure what is better to do here, since it is maybe odd that MSQ is using DruidQuery directly for stuff while this is filled with planner stuff, need to think about it a bit.

Comment on lines -343 to -350
if (query.getDataSource().getAnalysis().isJoin()) {
// Joins may require significant computation to compute the segmentMapFn. Offload it to a processor.
return new SimpleSegmentMapFnProcessor(query);
} else {
// Non-joins are expected to have cheap-to-compute segmentMapFn. Do the computation in the factory thread,
// without offloading to a processor.
return 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 this change? I guess the result is that above we always need a ChainedProcessorManager, is that necessary?

@@ -1187,6 +1149,11 @@ public OutputChannels getOutputChannels()
{
return outputChannels;
}

public ListenableFuture<OutputChannels> waitResultReadyAndGetSanityCheckedChannels()
Copy link
Member

Choose a reason for hiding this comment

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

i think this could just be called waitResultReady

/**
* Verifies there is exactly one channel per partition.
*/
public OutputChannels sanityCheck()
Copy link
Member

Choose a reason for hiding this comment

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

maybe we should call this verify() or verifySingleChannel()?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area - Batch Ingestion Area - MSQ For multi stage queries - https://github.com/apache/druid/issues/12262 Area - Querying
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants