Skip to content

[MSE] Add opt-in sender-sorted merging for global ordered windows - #19396

Open
xiangfu0 wants to merge 14 commits into
apache:masterfrom
xiangfu0:xiangfu0/pinot-issue-19395-ff8b8a
Open

xiangfu0 wants to merge 14 commits into
apache:masterfrom
xiangfu0:xiangfu0/pinot-issue-19395-ff8b8a

Conversation

@xiangfu0

@xiangfu0 xiangfu0 commented Aug 29, 2026 •

Copy link
Copy Markdown
Contributor

PR flow

Opt-in sender-sorted merging for global ordered windows: version homogeneity check → planner rule → k-way merge exchange → merge receive operator.

flowchart TD
  N0["BaseBrokerStarter init #40;F1#41;"]:::stAdded
  N1["KWayMergeSupportPredicate version check #40;F2#41;"]:::stAdded
  N2["MultiStageBrokerRequestHandler flag #40;F3#41;"]:::stModified
  N3["QueryEnvConf building #40;F3#44; F8#41;"]:::stModified
  N4["Planner rule decision #40;F7#41;"]:::stModified
  N5["PinotKWayMergeSortExchange creation #40;F6#44; F7#41;"]:::stAdded
  N6["KWayMergeExchangeNode planning #40;F15#41;"]:::stAdded
  N7["MailboxMergeReceiveNode creation #40;F11#44; F16#41;"]:::stAdded
  N8["SortedMailboxMergeReceiveOperator #40;F20#44; F22#41;"]:::stAdded
  N9["BlockingMultiStreamConsumer usage #40;F21#41;"]:::stModified
  N10["ServerPlanRequestVisitor unbounded sort handling #40;F23#41;"]:::stModified
  N0 -->|"creates and registers listener"| N1
  N1 -->|"passed to setter"| N2
  N2 -->|"read flag for config"| N3
  N3 -->|"provides isKWayMergeSupported"| N4
  N4 -->|"creates exchange when sortOnSender true"| N5
  N5 -->|"converts to planning exchange"| N6
  N6 -->|"creates mailbox merge receive"| N7
  N7 -->|"wraps in runtime operator"| N8
  N8 -->|"uses multi#8209;stream consumer"| N9
  N5 -->|"unbounded sort kept above leaf"| N10
  classDef stAdded fill:#dafbe1,stroke:#1a7f37,color:#1f2328,stroke-width:2px
  classDef stModified fill:#fff8c5,stroke:#9a6700,color:#1f2328,stroke-width:2px
  classDef stRemoved fill:#ffebe9,stroke:#cf222e,color:#1f2328,stroke-width:2px
  classDef stUnchanged fill:#f6f8fa,stroke:#656d76,color:#1f2328,stroke-width:1px
Loading

AI-generated · Green: added · Yellow: modified · Red: removed · Gray: existing

Partial evidence: 0 file patches omitted; 2 truncated.

Diff evidence
  • F1: pinot-broker/src/main/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarter.java — before · after
  • F2: pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/KWayMergeSupportPredicate.java — after
  • F3: pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/MultiStageBrokerRequestHandler.java — before · after
  • F6: pinot-query-planner/src/main/java/org/apache/pinot/calcite/rel/logical/PinotKWayMergeSortExchange.java — after
  • F7: pinot-query-planner/src/main/java/org/apache/pinot/calcite/rel/rules/PinotWindowExchangeNodeInsertRule.java — before · after
  • F8: pinot-query-planner/src/main/java/org/apache/pinot/query/QueryEnvironment.java — before · after
  • F11: pinot-query-planner/src/main/java/org/apache/pinot/query/planner/logical/PlanFragmenter.java — before · after
  • F15: pinot-query-planner/src/main/java/org/apache/pinot/query/planner/plannode/KWayMergeExchangeNode.java — after
  • F16: pinot-query-planner/src/main/java/org/apache/pinot/query/planner/plannode/MailboxMergeReceiveNode.java — after
  • F20: pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/SortedMailboxMergeReceiveOperator.java — after
  • F21: pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/utils/BlockingMultiStreamConsumer.java — before · after
  • F22: pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/plan/PlanNodeToOpChain.java — before · after
  • F23: pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/plan/server/ServerPlanRequestVisitor.java — before · after
  • Regenerate PR flow

Global ordered windows can keep an explicit Sort on each sender and use a logical k-way merge exchange with a distinct merge receive. Plain sending mailboxes transport the ordered input. The feature remains opt-in; matching immutable release versions are required, and missing, unknown, mixed, unreadable or SNAPSHOT versions and multi-cluster queries retain the compatible receiver-sort plan. The cached capability check is a point-in-time observation.

Receiver-side window Sorts explicitly retain complete input with MAX fetch and zero offset, including following frames and RANGE peers beyond response caps. Plan expectations were corrected at 124 internal Sort lines in 122 window queries; SQL, results, assertions, ignored flags, outer limits, frames and other plan fields remain unchanged. Independent review compared every corrected expected output against the hosted actual plan. The stalled-sender read-ahead follow-up remains #19395.

Validation at b047dd479ea360f19cc8ea13595a874590ed66de: all 16 hosted PR checks passed, including both unit sets, both integration sets, all four compatibility lanes, quickstart, Java 11 client compatibility, linter and dependency/security checks. The hosted checkout was merge 78aea7a9c868893b2a1b693566fc2eed9e2bb7cf with base 4e27013f9647e95e1ad2a2198d9c26eda411f867. These results certify that checkout and source head; they do not certify later master changes.

Local warning/deprecation-enabled validation passes 962 cases: full ResourceBasedQueryPlansTest 593, QueryCompilationTest 246, WindowAggregateOperatorTest 122 and window rule 1, with zero failures/errors/skips. Scoped mandatory checks pass. The hosted planner suite also executed all 593 cases without failures/errors/skips, and current runtime/new-method execution is documented in the final audit. Counts overlap earlier validation and are not summed. Existing conditional or disabled hosted cases remain reported in their logs.

Maintainer architecture acceptance and independent review remain required. The four dependent PRs retain their agreed stack bases and feature-only diffs; full child CI remains subject to prerequisite landing and the agreed base update.

@xiangfu0 xiangfu0 added multi-stage Related to the multi-stage query engine query Related to query processing performance Related to performance optimization labels Aug 29, 2026
@codecov-commenter

codecov-commenter commented Aug 29, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.16760% with 71 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.30%. Comparing base (a42e748) to head (01af906).
⚠️ Report is 20 commits behind head on master.

Files with missing lines Patch % Lines
...me/operator/SortedMailboxMergeReceiveOperator.java 91.02% 3 Missing and 11 partials ⚠️
.../query/planner/logical/PlanNodeToRelConverter.java 0.00% 9 Missing ⚠️
...me/operator/utils/BlockingMultiStreamConsumer.java 78.04% 6 Missing and 3 partials ⚠️
...e/rel/rules/PinotWindowExchangeNodeInsertRule.java 63.63% 1 Missing and 7 partials ⚠️
...uery/planner/plannode/MailboxMergeReceiveNode.java 55.55% 5 Missing and 3 partials ⚠️
...he/pinot/query/planner/explain/PlanNodeMerger.java 0.00% 6 Missing and 1 partial ⚠️
.../query/planner/logical/EquivalentStagesFinder.java 16.66% 4 Missing and 1 partial ⚠️
...e/pinot/broker/broker/helix/BaseBrokerStarter.java 66.66% 2 Missing ⚠️
...oker/requesthandler/KWayMergeSupportPredicate.java 94.28% 0 Missing and 2 partials ⚠️
...requesthandler/MultiStageBrokerRequestHandler.java 71.42% 0 Missing and 2 partials ⚠️
... and 4 more
Additional details and impacted files
@@              Coverage Diff              @@
##             master   #19396       +/-   ##
=============================================
+ Coverage     58.05%   68.30%   +10.24%     
- Complexity        7     1450     +1443     
=============================================
  Files          2708     3525      +817     
  Lines        167054   229272    +62218     
  Branches      27265    36389     +9124     
=============================================
+ Hits          96987   156593    +59606     
+ Misses        61910    60400     -1510     
- Partials       8157    12279     +4122     
Flag Coverage Δ
integration 100.00% <ø> (ø)
integration1 100.00% <ø> (ø)
integration2 0.00% <ø> (?)
java-25 68.30% <80.16%> (+10.24%) ⬆️
lane-a 100.00% <ø> (ø)
lane-b 0.00% <ø> (ø)
temurin 68.30% <80.16%> (+10.24%) ⬆️
unittests 68.29% <80.16%> (+10.24%) ⬆️
unittests1 58.20% <79.03%> (+0.15%) ⬆️
unittests2 39.92% <12.56%> (?)

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

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch from afe7a5d to af8af6a Compare August 31, 2026 09:21
@gortiz

gortiz commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

We are already working on something like that in #19120, #19121 and #19122. I would recommend coordinating our efforts.

@gortiz

gortiz commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

I've been working on my own fix for SortedMailboxReceiverOperator, which goes back to what used to be:

┌───────────────────────────────────┬─────────────────────────┬──────────────────────┐
│                                   │ #19396                  │      My branch       │
├───────────────────────────────────┼─────────────────────────┼──────────────────────┤
│                                   │ sortOnSender =          │ sortOnReceiver =     │
│ PinotWindowExchangeNodeInsertRule │ **true**, keeps         │ **false** + explicit │
│                                   │ sortOnReceiver = true   │  Sort                │
├───────────────────────────────────┼─────────────────────────┼──────────────────────┤
│                                   │ +336 lines — k-way      │                      │
│ SortedMailboxReceiveOperator      │ merge over sorted       │ @Deprecated          │
│                                   │ senders                 │                      │
├───────────────────────────────────┼─────────────────────────┼──────────────────────┤
│ MailboxSendOperator               │ +143 — sorts sender     │ untouched            │
│                                   │ output, 10k blocks      │                      │
├───────────────────────────────────┼─────────────────────────┼──────────────────────┤
│                                   │ new sortedOnSender      │                      │
│ Mailbox protocol                  │ confirmation over gRPC  │ untouched            │
│                                   │ + in-memory             │                      │
├───────────────────────────────────┼─────────────────────────┼──────────────────────┤
│ PinotSortExchangeNodeInsertRule   │ comment only —          │ sortOnReceiver =     │
│                                   │ deliberately deferred   │ false                │
└───────────────────────────────────┴─────────────────────────┴──────────────────────┘

The idea I have is to stop generating SortedMailboxReceiveOperator and substitute that with a sort on the receiver side (with optional sort on the sender side when the limit is small). Once we have that, we can start thinking about recovering SortedMailboxReceiveOperator as a k-way merge when the senders guarantee data is sent in order, which is what you and #19121 are doing (although #19121 keeps both the current and the k-way merge).

Also, I don't think MailboxSendOperator should sort on send. Instead, we should add a sort operator on the sender opchain and keep MailboxSendOperator agnostic about ordering.

@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch 2 times, most recently from cafa948 to f151331 Compare September 1, 2026 09:48
@xiangfu0 xiangfu0 changed the title [MSE] Support sender-side sorting for sort exchanges [MSE] Merge sender-sorted streams for ordered windows Sep 1, 2026
@xiangfu0

xiangfu0 commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

@gortiz I rebased this onto current master and refactored it around the coordination feedback.

Validation on head f151331206ca6a13157b1d93e55bb889d4c39c25: the 20-module runtime reactor passed (planner 1,540 tests; runtime 4,640 tests, 18 skips), 348 focused planner/runtime tests passed, all four hygiene gates passed for planner/runtime/perf, and the eight-domain Pinot review completed with no remaining findings. The refreshed 400k-row matched JMH comparison was noisy in both directions, so I reported the raw values in the PR body without making a performance claim.

@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch 5 times, most recently from fa82748 to e968380 Compare September 8, 2026 09:08
@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch 2 times, most recently from 515927f to f87d986 Compare September 23, 2026 21:36
@xiangfu0

xiangfu0 commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Rebased onto master after #19412 and kept the responsibilities separate: sender sorting owns ordering; #19396 k-way merges only confirmed-sorted local/gRPC streams and safely falls back for mixed/custom transports.

Final coverage review added two targeted regressions for queued read-ahead preservation during fallback and buffered-cursor cleanup on sender error. The focused class passes 21/21, module formatting/checkstyle/license gates pass, and Codecov improved to 91.37% patch coverage.

Exact head 9642c66b99 is conflict-free and all 13 check runs pass. The linter setup failure was a transient Maven Central resolution miss; retrying only that job passed. No review threads remain; maintainer approval is the only remaining gate.

@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch 2 times, most recently from 9642c66 to 7ecc01c Compare September 24, 2026 01:38
@xiangfu0

xiangfu0 commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor Author

Rebased and simplified on top of master 257a0e7df2 (which includes #19412); the updated PR head is 7ecc01c0fd. The patch shrank from 38 to 27 files and from 2,379 to 1,957 changed lines, with the benchmark harness kept temporary and out of the PR.

Fresh matched JMH results on JDK 25, 400k rows, two servers, local + gRPC fan-in:

Ordered window Rebased master PR Mean change
Global 193.400 ± 9.810 ms/op (3 forks, 15 measurements) 137.801 ± 14.177 ms/op -28.7%
Partitioned 247.859 ± 27.999 ms/op (2 forks, 10 measurements) 184.532 ± 31.146 ms/op -25.5%

Both JMH-reported intervals are non-overlapping. Global is the stronger signal: every PR measurement was below every baseline measurement. The partitioned aggregate also favors the PR, but visible fork variance means 25.5% is this run's estimate, not a stable production-wide effect size.

Local validation passed: 89 focused runtime tests, all 243 QueryCompilationTest cases, and planner/runtime Spotless, Checkstyle, and license gates. Fresh exact-head CI is now running after the force-with-lease update.

@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch from 7ecc01c to 5aeb374 Compare September 24, 2026 09:35
@xiangfu0 xiangfu0 changed the title [MSE] Merge sender-sorted streams for ordered windows [MSE] Merge sender-sorted streams for global ordered windows Sep 24, 2026
@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch from aa52944 to 10dd7e9 Compare September 25, 2026 12:47

@gortiz gortiz 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.

Thanks for the thorough PR description and benchmark matrix; the design is careful about mixed-version compatibility.

Main requests:

  1. Drop the no-op Sort above the exchange when the exchange sorts on the receiver (inline at PinotWindowExchangeNodeInsertRule). Every receiver already returns rows in order. On new servers the Sort is a pass-through, and on old servers it is a second full sort. With it gone, SortOperator.isInputSorted and SortedMultiStageOperator are no longer needed.
  2. Add a kill switch: a broker config plus a query option, in the style of sortExchangeCopyThreshold, but as a boolean, because the window Sort has no fetch for a threshold to act on.
  3. Rolling upgrade: with a new broker and old servers, the same rows can be sorted several times (old leaf V1 ORDER BY ... LIMIT 2147483647, old receiver full sort, old Sort above it). Results stay correct, but queries are slower until the upgrade finishes.
  4. Tests: a randomized merge-vs-full-sort test (senders, block splits, tie density, starvation order) would protect the equal-head / lazy-heap logic.

Other comments are inline; several are nits or confirmations.

@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch from 8eee817 to 2673b61 Compare September 26, 2026 04:52
@xiangfu0

Copy link
Copy Markdown
Contributor Author

@gortiz Thanks for the detailed review. Final head 2673b6149f is rebased on current master and addresses the requests: the optimization is default-off with broker/query controls, the redundant receiver-side Sort and no-op machinery are removed, and randomized merge plus implementation-plan/op-chain coverage are added. I also documented the remaining unbounded read-ahead under open #19395 and deferred the nonblocking shared consumer API cleanup. All 14 inline threads now have evidence-backed replies and are resolved; fresh exact-head CI is running.

@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch from 9163e7e to 1feb422 Compare September 28, 2026 22:51
@xiangfu0

Copy link
Copy Markdown
Contributor Author

Update to supersede my September 26 default-off summary: current head 1feb42217b is rebased on master a3af29e92b and makes windowSortOnSender=auto the default. AUTO chooses separately for each global ordered-window exchange; unknown or nonqualifying shapes keep the receiver full sort, and explicit true/false remain available.

The PR description now includes the new A–B–B–A and same-cluster paired measurements, including the remaining small/uncertain fallback overhead. Focused tests, package build, formatting, checkstyle, license, and added-line warning checks passed locally. Exact-head CI is running; no unresolved review thread remains. I am not claiming a universal no-regression guarantee or requesting merge before CI/re-review.

@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch from 1feb422 to 6843676 Compare September 30, 2026 07:49
@xiangfu0 xiangfu0 changed the title [MSE] Merge sender-sorted streams for global ordered windows [MSE] Add opt-in sender-sorted merging for global ordered windows Sep 30, 2026
@xiangfu0
xiangfu0 marked this pull request as draft September 30, 2026 07:51
@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch from 6843676 to 555f55c Compare September 30, 2026 15:54
@xiangfu0
xiangfu0 marked this pull request as ready for review September 30, 2026 16:00
Make the optimization opt-in, remove the redundant receiver sort, and add randomized and plan-contract coverage.
Reproduce: run globalPresortedWindow with four senders and windowSortOnSender=true. Use a two-level tournament to reduce per-row comparisons, with a 10k-row boundary test.
Use one priority queue merge path and keep rollout fallback, bounded output and mailbox progress handling. Enable windowSortOnSender=true for global ordered windows; the default remains receiver sorting.
Compile queries before planning and explaining, and document the intentional legacy receiver assertion. This keeps the sender-sorted window tests free of new deprecation warnings.
@xiangfu0
xiangfu0 force-pushed the xiangfu0/pinot-issue-19395-ff8b8a branch from 555f55c to 6dff651 Compare September 30, 2026 19:06
@gortiz

gortiz commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

I'd like to use this PR to fix how MSE assigns the responsibility for ordering. Today, ordering should be a requirement that the logical plan guarantees. Instead, the physical plan and the runtime keep getting extra machinery to guarantee it: sort/sortedOnSender on the exchange and mailbox nodes, SortedMailboxReceiveOperator, and now a per-block sorted.on.sender marker. I consider the marker a blocker.

The runtime has to trust the plan. Re-checking ordering on every block is like a JIT adding checks for invariants that the front-end compiler already proved. It is also fragile: MailboxSendOperator.isSortedOnSender() requires a SortOperator right below the send, so any order-preserving operator we add there later (a buffer, for example) silently disables the optimization. And it goes through the whole mailbox layer (GrpcSendingMailbox, InMemorySendingMailbox, MailboxService, ReceivingMailbox, MailboxContentObserver, ChannelUtils, BlockingMultiStreamConsumer) for an opt-in feature.

What I'd suggest instead is to express ordering with simple plan nodes, not flags:

On the Calcite side, this could be a new PinotKWayMergeSortExchange: an exchange that requires its input to be sorted on the collation and preserves that order in its output. PlanFragmenter would turn it into a plain MailboxSendNode plus the new merge receive node. A rule similar to PinotSortExchangeCopyRule could push the limit/offset of a Sort above it into the receive.

In practice, for this PR that means removing the mailbox metadata and the sortedOnSender parameter of offer()/offerRaw(), MseBlockWithStats.isSortedOnSender(), isLastBlockSortedOnSender(), MailboxSendOperator.isSortedOnSender(), hasExplicitSortInput() and the full-sort fallback in the merge receiver. A per-row order check is fine in tests, but not as a production path.

Compatibility gets simpler too. On a new server:

Plan Comes from New server
plain receive current broker MailboxReceiveOperator
receive with sort=true broker older than #19412 MailboxReceiveOperator + SortOperator
new merge receive node new broker, option enabled k-way merge

For a new broker with old servers, it's the broker's responsibility not to send the new node and to keep generating a plan that old servers understand, i.e. a plain receive with a Sort downstream. We already have the mechanism for this: SendStatsPredicate in SAFE mode watches the instance configs and detects when any broker or server reports a different Pinot version. Today only servers use it to decide whether to send MSE stats, but the broker can reuse the same logic and only pick PinotKWayMergeSortExchange when the cluster is homogeneous. As a last line of defense, an old server can't deserialize the new node (PlanNodeDeserializer throws Unsupported PlanNode type), so the query fails loudly instead of returning wrong results.

With this, sortedOnSender and sort in plan.proto and the flags in PinotLogicalSortExchange can be deprecated, and SortedMailboxReceiveOperator can go away. Old ORDER BY plans already have a Sort with the fetch above the receive, so they get the bounded implementation with a LIMIT. For old window plans, the server injects a Sort without a fetch. That part can be a follow-up.

Expect the explicit MAX_VALUE fetch on receiver sorts below ordered
windows. This preserves complete window input when a response cap is
configured; SQL limits, window frames and ordering remain unchanged.

Update only the 122 affected golden outputs (124 sort nodes). The full
593-case plan suite and existing complete-window regressions pass.
@xiangfu0

xiangfu0 commented Oct 4, 2026

Copy link
Copy Markdown
Contributor Author

@gortiz updated at 01af90617f. Ordering is now a logical-plan guarantee: an explicit Sort feeds PinotKWayMergeSortExchange, and fragmentation creates a plain sender plus a distinct merge receive with serialized optional fetch/offset. Mailbox block markers, sender structural checks, production row-order checks, and the new merge receiver's full-sort fallback are removed.

The broker gate requires matching, non-SNAPSHOT broker/server release versions and fails closed on missing/unreadable configs, registration failure or disconnect; multi-cluster queries disable it. Unsupported clusters use plain receive plus an explicit MAX-fetch Sort, preserving complete window input. Legacy sort=true plans still use the deprecated full-sort receiver; its replacement and old-flag cleanup remain follow-up work. The gate is a point-in-time snapshot, so a concurrent version/topology change can still cause a loud unsupported-node query failure.

Recent unchanged planner/window coverage passed 962 cases, including full-input following/RANGE regressions. This latest commit only corrects the existing SNAPSHOT assertion (+7/-3 lines); both broker gate tests, JDK25 warning-enabled compilation, formatting, checkstyle and license checks passed, with no warnings on added lines. All 17 reported checks were green at b047dd4; CI is running on the new head. Please re-review the architecture and retained legacy compatibility path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

multi-stage Related to the multi-stage query engine performance Related to performance optimization query Related to query processing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants