Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@

package org.opensearch.sql.calcite.remote;

import static org.junit.Assume.assumeFalse;
import static org.opensearch.sql.legacy.TestsConstants.*;
import static org.opensearch.sql.util.Capability.MULTISEARCH_COLUMN_ORDER;
import static org.opensearch.sql.util.Capability.MULTISEARCH_SAME_INDEX_CONFLATION;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
import static org.opensearch.sql.util.MatcherUtils.verifySchema;
import static org.opensearch.sql.util.MatcherUtils.verifySchemaInOrder;

import java.io.IOException;
import org.json.JSONObject;
Expand All @@ -31,6 +33,7 @@ public void init() throws Exception {
loadIndex(Index.TIME_TEST_DATA);
loadIndex(Index.TIME_TEST_DATA2);
loadIndex(Index.LOCATIONS_TYPE_CONFLICT);
loadIndex(Index.DATA_TYPE_ALIAS);
}

@Test
Expand Down Expand Up @@ -462,4 +465,42 @@ public void testMultisearchTypeConflictWithStats() {
.getMessage()
.contains("Unable to process column 'age' due to incompatible types:"));
}

/**
* Regression test for GitHub issue #5533. When {@code @timestamp} is defined as a field-type
* alias in the index mapping, multisearch used to throw:
*
* <pre>ClassCastException: RelCompositeTrait cannot be cast to RelCollation</pre>
*
* <p>Root cause: {@code reIndexCollations()} and {@code pushDownSort()} both used {@code
* RelTraitSet.plus()} which composes collation traits into a {@link
* org.apache.calcite.rel.RelCompositeTrait} when a collation is already present. Calcite's {@code
* RelTraitSet.getCollation()} then fails with a ClassCastException. Fixed by using {@code
* RelTraitSet.replace()} instead to always replace the collation trait.
*/
@Test
public void testMultisearchWithTimestampAliasFieldDoesNotThrow() throws IOException {
// alias-typed fields are stripped when loading indices in analytics-engine parquet mode,
// so @timestamp does not exist in TEST_INDEX_ALIAS on that route.
assumeFalse(
"alias-typed fields are stripped in analytics-engine parquet mode;"
+ " @timestamp won't exist in TEST_INDEX_ALIAS on that route.",
isAnalyticsParquetIndicesEnabled());
// TEST_INDEX_ALIAS has @timestamp defined as an alias field pointing to original_date.
// Running multisearch on such an index used to crash with ClassCastException.
JSONObject result =
executeQuery(
String.format(
"| multisearch "
+ "[search source=%s | where original_col > 1 | fields original_col,"
+ " @timestamp] "
+ "[search source=%s | where original_col = 1 | fields original_col,"
+ " @timestamp]",
TEST_INDEX_ALIAS, TEST_INDEX_ALIAS));

verifySchemaInOrder(
result, schema("original_col", null, "int"), schema("@timestamp", null, "timestamp"));
// 2 rows from original_col > 1, 1 row from original_col = 1
assertEquals(3, result.getInt("total"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ && isAnyCollationNameInAggregators(collationNames)) {
// aggregators.
return null;
}
RelTraitSet traitsWithCollations = getTraitSet().plus(RelCollations.of(collations));
RelTraitSet traitsWithCollations = getTraitSet().replace(RelCollations.of(collations));
PushDownContext pushDownContextWithoutSort = this.pushDownContext.cloneWithoutSort();
AbstractAction<?> action;
Object digest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ private RelTraitSet reIndexCollations(List<Integer> selectedColumns) {
collation ->
collation.withFieldIndex(selectedColumns.indexOf(collation.getFieldIndex())))
.collect(Collectors.toList());
newTraitSet = getTraitSet().plus(RelCollations.of(newCollations));
newTraitSet = getTraitSet().replace(RelCollations.of(newCollations));
} else {
newTraitSet = getTraitSet();
}
Expand Down
Loading