|
5 | 5 |
|
6 | 6 | package org.opensearch.sql.opensearch.storage.scan; |
7 | 7 |
|
8 | | -import static org.opensearch.sql.opensearch.storage.serde.ScriptParameterHelper.MISSING_MAX; |
9 | | - |
10 | 8 | import com.google.common.collect.ImmutableList; |
11 | | -import java.util.ArrayList; |
12 | | -import java.util.LinkedHashMap; |
13 | 9 | import java.util.List; |
14 | 10 | import java.util.Map; |
15 | 11 | import java.util.Objects; |
16 | | -import java.util.function.Supplier; |
17 | 12 | import java.util.stream.Collectors; |
18 | 13 | import lombok.Getter; |
19 | 14 | import org.apache.calcite.plan.Convention; |
|
26 | 21 | import org.apache.calcite.rel.RelCollation; |
27 | 22 | import org.apache.calcite.rel.RelCollations; |
28 | 23 | import org.apache.calcite.rel.RelFieldCollation; |
29 | | -import org.apache.calcite.rel.RelFieldCollation.Direction; |
30 | 24 | import org.apache.calcite.rel.core.Aggregate; |
31 | 25 | import org.apache.calcite.rel.core.Filter; |
32 | 26 | import org.apache.calcite.rel.core.Project; |
|
37 | 31 | import org.apache.calcite.rel.type.RelDataTypeFactory; |
38 | 32 | import org.apache.calcite.rel.type.RelDataTypeField; |
39 | 33 | import org.apache.calcite.rex.RexBuilder; |
40 | | -import org.apache.calcite.rex.RexCall; |
41 | 34 | import org.apache.calcite.rex.RexNode; |
42 | 35 | import org.apache.calcite.sql.fun.SqlStdOperatorTable; |
43 | | -import org.apache.calcite.sql.type.SqlTypeName; |
44 | 36 | import org.apache.commons.lang3.tuple.Pair; |
45 | 37 | import org.apache.logging.log4j.LogManager; |
46 | 38 | import org.apache.logging.log4j.Logger; |
47 | 39 | import org.opensearch.search.aggregations.AggregationBuilder; |
48 | 40 | import org.opensearch.search.aggregations.bucket.composite.CompositeAggregationBuilder; |
49 | | -import org.opensearch.search.sort.ScriptSortBuilder.ScriptSortType; |
50 | | -import org.opensearch.search.sort.SortBuilder; |
51 | | -import org.opensearch.search.sort.SortBuilders; |
52 | | -import org.opensearch.search.sort.SortOrder; |
53 | 41 | import org.opensearch.sql.ast.expression.Argument; |
54 | 42 | import org.opensearch.sql.calcite.utils.OpenSearchTypeFactory; |
55 | 43 | import org.opensearch.sql.common.setting.Settings; |
|
60 | 48 | import org.opensearch.sql.opensearch.planner.rules.EnumerableIndexScanRule; |
61 | 49 | import org.opensearch.sql.opensearch.planner.rules.OpenSearchIndexRules; |
62 | 50 | import org.opensearch.sql.opensearch.request.AggregateAnalyzer; |
63 | | -import org.opensearch.sql.opensearch.request.OpenSearchRequestBuilder.PushDownUnSupportedException; |
64 | 51 | import org.opensearch.sql.opensearch.request.PredicateAnalyzer; |
65 | 52 | import org.opensearch.sql.opensearch.request.PredicateAnalyzer.QueryExpression; |
66 | 53 | import org.opensearch.sql.opensearch.response.agg.OpenSearchAggregationResponseParser; |
|
74 | 61 | import org.opensearch.sql.opensearch.storage.scan.context.PushDownContext; |
75 | 62 | import org.opensearch.sql.opensearch.storage.scan.context.PushDownType; |
76 | 63 | import org.opensearch.sql.opensearch.storage.scan.context.RareTopDigest; |
77 | | -import org.opensearch.sql.opensearch.storage.scan.context.SortExprDigest; |
78 | 64 |
|
79 | 65 | /** The logical relational operator representing a scan of an OpenSearchIndex type. */ |
80 | 66 | @Getter |
@@ -440,98 +426,4 @@ public AbstractRelNode pushDownLimit(LogicalSort sort, Integer limit, Integer of |
440 | 426 | } |
441 | 427 | return null; |
442 | 428 | } |
443 | | - |
444 | | - /** |
445 | | - * Push down sort expressions to OpenSearch level. Supports mixed RexCall and field sort |
446 | | - * expressions. |
447 | | - * |
448 | | - * @param sortExprDigests List of SortExprDigest with expressions and collation information |
449 | | - * @return CalciteLogicalIndexScan with sort expressions pushed down, or null if pushdown fails |
450 | | - */ |
451 | | - public CalciteLogicalIndexScan pushdownSortExpr(List<SortExprDigest> sortExprDigests) { |
452 | | - try { |
453 | | - if (sortExprDigests == null || sortExprDigests.isEmpty()) { |
454 | | - return null; |
455 | | - } |
456 | | - |
457 | | - CalciteLogicalIndexScan newScan = |
458 | | - new CalciteLogicalIndexScan( |
459 | | - getCluster(), |
460 | | - traitSet, |
461 | | - hints, |
462 | | - table, |
463 | | - osIndex, |
464 | | - getRowType(), |
465 | | - pushDownContext.cloneWithoutSort()); |
466 | | - |
467 | | - List<Supplier<SortBuilder<?>>> sortBuilderSuppliers = new ArrayList<>(); |
468 | | - for (SortExprDigest digest : sortExprDigests) { |
469 | | - SortOrder order = |
470 | | - Direction.DESCENDING.equals(digest.getDirection()) ? SortOrder.DESC : SortOrder.ASC; |
471 | | - |
472 | | - if (digest.isSimpleFieldReference()) { |
473 | | - String missing = |
474 | | - switch (digest.getNullDirection()) { |
475 | | - case FIRST -> "_first"; |
476 | | - case LAST -> "_last"; |
477 | | - default -> null; |
478 | | - }; |
479 | | - sortBuilderSuppliers.add( |
480 | | - () -> SortBuilders.fieldSort(digest.getFieldName()).order(order).missing(missing)); |
481 | | - continue; |
482 | | - } |
483 | | - RexNode sortExpr = digest.getExpression(); |
484 | | - assert sortExpr instanceof RexCall : "sort expression should be RexCall"; |
485 | | - Map<String, Object> missingValueParams = |
486 | | - new LinkedHashMap<>() { |
487 | | - { |
488 | | - put(MISSING_MAX, digest.isMissingMax()); |
489 | | - } |
490 | | - }; |
491 | | - // Complex expression - use ScriptQueryExpression to generate script for sort |
492 | | - PredicateAnalyzer.ScriptQueryExpression scriptExpr = |
493 | | - new PredicateAnalyzer.ScriptQueryExpression( |
494 | | - digest.getExpression(), |
495 | | - rowType, |
496 | | - osIndex.getAllFieldTypes(), |
497 | | - getCluster(), |
498 | | - missingValueParams); |
499 | | - // Determine the correct ScriptSortType based on the expression's return type |
500 | | - ScriptSortType sortType = getScriptSortType(sortExpr.getType()); |
501 | | - |
502 | | - sortBuilderSuppliers.add( |
503 | | - () -> SortBuilders.scriptSort(scriptExpr.getScript(), sortType).order(order)); |
504 | | - } |
505 | | - |
506 | | - // Create action to push down sort expressions to OpenSearch |
507 | | - OSRequestBuilderAction action = |
508 | | - requestBuilder -> requestBuilder.pushDownSortSuppliers(sortBuilderSuppliers); |
509 | | - |
510 | | - newScan.pushDownContext.add(PushDownType.SORT_EXPR, sortExprDigests, action); |
511 | | - return newScan; |
512 | | - } catch (Exception e) { |
513 | | - if (LOG.isDebugEnabled()) { |
514 | | - LOG.debug("Cannot pushdown sort expressions: {}", sortExprDigests, e); |
515 | | - } |
516 | | - } |
517 | | - return null; |
518 | | - } |
519 | | - |
520 | | - /** |
521 | | - * Determine the appropriate ScriptSortType based on the expression's return type. |
522 | | - * |
523 | | - * @param relDataType the return type of the expression |
524 | | - * @return the appropriate ScriptSortType |
525 | | - */ |
526 | | - private ScriptSortType getScriptSortType(RelDataType relDataType) { |
527 | | - if (SqlTypeName.CHAR_TYPES.contains(relDataType.getSqlTypeName())) { |
528 | | - return ScriptSortType.STRING; |
529 | | - } else if (SqlTypeName.INT_TYPES.contains(relDataType.getSqlTypeName()) |
530 | | - || SqlTypeName.APPROX_TYPES.contains(relDataType.getSqlTypeName())) { |
531 | | - return ScriptSortType.NUMBER; |
532 | | - } else { |
533 | | - throw new PushDownUnSupportedException( |
534 | | - "Unsupported type for sort expression pushdown: " + relDataType); |
535 | | - } |
536 | | - } |
537 | 429 | } |
0 commit comments