Skip to content

Commit d6ab5a5

Browse files
committed
Add integration test for vectorSearch() alias with multiple backing indices
Signed-off-by: Eric Wei <mengwei.eric@gmail.com>
1 parent 394c190 commit d6ab5a5

1 file changed

Lines changed: 67 additions & 0 deletions

File tree

integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchIT.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,11 +677,78 @@ public void testTrailingCommaInVectorRejected() throws IOException {
677677
assertThat(ex.getMessage(), containsString("trailing or consecutive commas"));
678678
}
679679

680+
// ── Alias with multiple backing indices ───────────────────────────────
681+
// vectorSearch() accepts an alias as `table=`. When the alias points at multiple backing
682+
// indices, planning must accept the alias string instead of treating it as a wildcard or
683+
// multi-target. Execution correctness over compatible knn_vector mappings is a separate
684+
// concern covered by k-NN-enabled tests/follow-up; these tests lock in planning acceptance
685+
// only, via _explain on the default no-kNN cluster.
686+
687+
@Test
688+
public void testExplainOverAliasWithMultipleBackingIndices() throws IOException {
689+
// Create two indices with identical keyword mappings (no knn_vector, since the plugin is
690+
// not installed) and a shared alias. We only assert the planner accepts the alias; whether
691+
// k-NN accepts the alias at execution is a separate concern tested on a k-NN-enabled
692+
// cluster.
693+
// Randomized names so a stale alias/index left by an aborted prior run of this class does
694+
// not shadow a fresh setup — a concrete risk on local reruns.
695+
String suffix = java.util.UUID.randomUUID().toString().replace("-", "").substring(0, 8);
696+
String idx1 = "vector_alias_backing_1_" + suffix;
697+
String idx2 = "vector_alias_backing_2_" + suffix;
698+
String alias = "vector_alias_combined_" + suffix;
699+
try {
700+
createSimpleIndex(idx1);
701+
createSimpleIndex(idx2);
702+
addToAlias(idx1, alias);
703+
addToAlias(idx2, alias);
704+
705+
String explain =
706+
explainQuery(
707+
"SELECT v._id FROM vectorSearch(table='"
708+
+ alias
709+
+ "', field='embedding', vector='[1.0, 2.0]', option='k=5') AS v");
710+
711+
assertThat(explain, containsString("VectorSearchIndexScan"));
712+
assertThat(explain, containsString(alias));
713+
} finally {
714+
// Deleting the backing indices removes the alias automatically, but delete the alias
715+
// first for robustness against partial setup failures.
716+
deleteAliasIfExists(alias);
717+
deleteIndexIfExists(idx1);
718+
deleteIndexIfExists(idx2);
719+
}
720+
}
721+
722+
private void createSimpleIndex(String indexName) throws IOException {
723+
Request create = new Request("PUT", "/" + indexName);
724+
create.setJsonEntity("{\"mappings\":{\"properties\":{\"state\":{\"type\":\"keyword\"}}}}");
725+
client().performRequest(create);
726+
}
727+
728+
private void addToAlias(String indexName, String aliasName) throws IOException {
729+
Request req = new Request("POST", "/_aliases");
730+
req.setJsonEntity(
731+
"{\"actions\":[{\"add\":{\"index\":\""
732+
+ indexName
733+
+ "\",\"alias\":\""
734+
+ aliasName
735+
+ "\"}}]}");
736+
client().performRequest(req);
737+
}
738+
680739
private void deleteIndexIfExists(String indexName) {
681740
try {
682741
client().performRequest(new Request("DELETE", "/" + indexName));
683742
} catch (IOException ignored) {
684743
// Index does not exist, which is fine.
685744
}
686745
}
746+
747+
private void deleteAliasIfExists(String aliasName) {
748+
try {
749+
client().performRequest(new Request("DELETE", "/_all/_alias/" + aliasName));
750+
} catch (IOException ignored) {
751+
// Alias does not exist, which is fine.
752+
}
753+
}
687754
}

0 commit comments

Comments
 (0)