Skip to content

Commit f1bc872

Browse files
committed
Merge upstream/main into feature/mustang-ppl-integration
Brings the branch up to current upstream/main (54 commits since the last catch-up at #5397, divergence point 513e1b2). Preserves both parents so commit lineage from main is retained on the feature branch. ### Main commits absorbed (54 since divergence) Highlights: - #5419 Register LENGTH/REGEXP_REPLACE/DATE_TRUNC in unified function spec - #5408 Normalize datetime types for unified query API - #5414 Gradle wrapper 9.4.1 bump + exclude @ignore classes - #5399 [BugFix] Scope SQL cursor continuation to original query indices under FGAC - #5394 [Feature] Support SQL Vector Search - #5361 Version bump to OpenSearch 3.7 (Jackson 2 → 3 parser API) - #5360 Define unified SQL language spec with composable extensions - #5240 [FEATURE] Union command in PPL - #5266 Initial implementation of report-builder interface - #5278 isnotnull condition support - #3922, #4659, #4800, #5099, #5169, #5172, #5175, #5185, #5347, #5370 and other bugfixes - 34 others (bugfixes, doc updates, infra) ### Conflict resolutions Seven content conflicts resolved during the merge. Resolution kept the feature branch's analytics-engine-path semantics where main's changes would have regressed them. - api/.../UnifiedQueryContext.java Blank-line-only conflict in Builder.build(); took main's tighter formatting (no extra blank). - core/.../executor/QueryService.java Main reformatted executeWithCalcite without the CalciteClassLoaderHelper.withCalciteClassLoader() wrapper. Kept the feature-branch wrapping — required for analytics-engine classloader isolation — and the matching import. Same shape applies to explainWithCalcite which git auto-merged correctly. - integ-test/build.gradle Both sides added @Ignore-class exclusions to work around the Gradle 9.4.1 TestEventReporterAsListener ClassCastException. Took the feature-branch's detailed root-cause comment, kept ASCII ordering of the JSONRequestIT/JoinIT and SQLFunctionsIT/ShowIT/SourceFieldIT entries. - integ-test/.../CalciteEvalCommandIT.java Feature branch wraps test-data PUTs in if (!TestUtils.isIndexExist(...)) for idempotency on the helper-managed-index analytics-engine compatibility run; main has the unguarded PUTs. Kept feature's idempotency guards for both test_eval and test_eval_agent. - legacy/.../RestSqlAction.java Feature branch added delegateToV2Engine(...) (extracted from the analytics-engine routing path) and ALSO has handleException / getRestStatus / getRawErrorCode; main added the latter three in the same position. Kept feature's delegateToV2Engine, kept one copy of the helpers, removed the duplicate set that git produced. - plugin/.../SQLPlugin.java Both sides expanded the executor import block. Kept the union: ExecutionEngine + ExecutionEngine.ExplainResponse + QueryType (all three are referenced in this file). - plugin/.../transport/TransportPPLQueryAction.java Main now passes engine extensions to OpenSearchPluginModule via extensionsHolder.engines(). Feature creates a local pluginSettings for the unified-query handler. Combined both — kept the extensions-aware module construction *and* the pluginSettings / pluginSettingsRef wiring. EngineExtensionsHolder is a new file from main (#5298) preserved as-is. ### Verification - ./gradlew :api:compileJava :core:compileJava :legacy:compileJava :opensearch-sql-plugin:compileJava :integ-test:compileTestJava passes locally Signed-off-by: Kai Huang <ahkcs@amazon.com>
2 parents f006e29 + 0ff1eec commit f1bc872

5 files changed

Lines changed: 52 additions & 8 deletions

File tree

api/src/main/java/org/opensearch/sql/api/UnifiedQueryContext.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ public UnifiedQueryContext build() {
234234
case SQL -> UnifiedSqlSpec.extended();
235235
case PPL -> UnifiedPplSpec.create();
236236
};
237-
238237
Settings settings = buildSettings();
239238
CalcitePlanContext planContext =
240239
CalcitePlanContext.create(

integ-test/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -601,8 +601,8 @@ integTest {
601601
// even though the tests would have been skipped anyway. The bridge is registered by Gradle's
602602
// own AbstractTestTask (we can't bypass it from user code), so the only available remedy is
603603
// to keep these classes off the test runner's input set. Net behaviour for CI: still
604-
// skipped, just at the build layer instead of inside JUnit. Remove once Gradle ships a fix.
605-
// OrderIT is already excluded above.
604+
// skipped, just at the build layer instead of inside JUnit. Remove once Gradle ships a fix
605+
// (not fixed as of 9.5.0). OrderIT is already excluded above.
606606
exclude 'org/opensearch/sql/calcite/remote/CalciteInformationSchemaCommandIT.class'
607607
exclude 'org/opensearch/sql/calcite/remote/CalciteJsonFunctionsIT.class'
608608
exclude 'org/opensearch/sql/calcite/remote/CalcitePrometheusDataSourceCommandsIT.class'

plugin/src/main/java/org/opensearch/sql/plugin/SQLPlugin.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import org.opensearch.jobscheduler.spi.ScheduledJobParser;
5050
import org.opensearch.jobscheduler.spi.ScheduledJobRunner;
5151
import org.opensearch.plugins.ActionPlugin;
52+
import org.opensearch.plugins.ExtensiblePlugin;
5253
import org.opensearch.plugins.Plugin;
5354
import org.opensearch.plugins.ScriptPlugin;
5455
import org.opensearch.plugins.SystemIndexPlugin;
@@ -92,6 +93,7 @@
9293
import org.opensearch.sql.directquery.transport.model.ExecuteDirectQueryActionResponse;
9394
import org.opensearch.sql.directquery.transport.model.ReadDirectQueryResourcesActionResponse;
9495
import org.opensearch.sql.directquery.transport.model.WriteDirectQueryResourcesActionResponse;
96+
import org.opensearch.sql.executor.ExecutionEngine;
9597
import org.opensearch.sql.executor.ExecutionEngine.ExplainResponse;
9698
import org.opensearch.sql.executor.QueryType;
9799
import org.opensearch.sql.legacy.esdomain.LocalClusterState;
@@ -102,6 +104,7 @@
102104
import org.opensearch.sql.opensearch.setting.OpenSearchSettings;
103105
import org.opensearch.sql.opensearch.storage.OpenSearchDataSourceFactory;
104106
import org.opensearch.sql.opensearch.storage.script.CompoundedScriptEngine;
107+
import org.opensearch.sql.plugin.config.EngineExtensionsHolder;
105108
import org.opensearch.sql.plugin.config.OpenSearchPluginModule;
106109
import org.opensearch.sql.plugin.rest.AnalyticsExecutorHolder;
107110
import org.opensearch.sql.plugin.rest.RestPPLGrammarAction;
@@ -140,10 +143,15 @@
140143
import org.opensearch.watcher.ResourceWatcherService;
141144

142145
public class SQLPlugin extends Plugin
143-
implements ActionPlugin, ScriptPlugin, SystemIndexPlugin, JobSchedulerExtension {
146+
implements ActionPlugin,
147+
ScriptPlugin,
148+
SystemIndexPlugin,
149+
JobSchedulerExtension,
150+
ExtensiblePlugin {
144151

145152
private static final Logger LOGGER = LogManager.getLogger(SQLPlugin.class);
146153

154+
private List<ExecutionEngine> executionEngineExtensions = List.of();
147155
private ClusterService clusterService;
148156

149157
/** Settings should be inited when bootstrap the plugin. */
@@ -162,6 +170,18 @@ public String description() {
162170
return "Use sql to query OpenSearch.";
163171
}
164172

173+
@Override
174+
public void loadExtensions(ExtensionLoader loader) {
175+
List<ExecutionEngine> loaded = loader.loadExtensions(ExecutionEngine.class);
176+
this.executionEngineExtensions = loaded != null ? List.copyOf(loaded) : List.of();
177+
if (!executionEngineExtensions.isEmpty()) {
178+
LOGGER.info(
179+
"Loaded {} execution engine extension(s): {}",
180+
executionEngineExtensions.size(),
181+
executionEngineExtensions.stream().map(e -> e.getClass().getSimpleName()).toList());
182+
}
183+
}
184+
165185
@Override
166186
public List<RestHandler> getRestHandlers(
167187
Settings settings,
@@ -348,7 +368,7 @@ public Collection<Object> createComponents(
348368
LocalClusterState.state().setPluginSettings((OpenSearchSettings) pluginSettings);
349369
LocalClusterState.state().setClient(client);
350370
ModulesBuilder modules = new ModulesBuilder();
351-
modules.add(new OpenSearchPluginModule());
371+
modules.add(new OpenSearchPluginModule(executionEngineExtensions));
352372
modules.add(
353373
b -> {
354374
b.bind(NodeClient.class).toInstance((NodeClient) client);
@@ -383,12 +403,15 @@ public Collection<Object> createComponents(
383403
ScheduledAsyncQueryJobRunner.getJobRunnerInstance()
384404
.loadJobResource(client, clusterService, threadPool, asyncQueryExecutorService);
385405

406+
EngineExtensionsHolder extensionsHolder = new EngineExtensionsHolder(executionEngineExtensions);
407+
386408
return ImmutableList.of(
387409
dataSourceService,
388410
asyncQueryExecutorService,
389411
clusterManagerEventListener,
390412
pluginSettings,
391-
directQueryExecutorService);
413+
directQueryExecutorService,
414+
extensionsHolder);
392415
}
393416

394417
@Override
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.plugin.config;
7+
8+
import java.util.List;
9+
import org.opensearch.sql.executor.ExecutionEngine;
10+
11+
/**
12+
* Holds execution engine engines loaded via SPI. Returned from {@code SQLPlugin.createComponents()}
13+
* so that OpenSearch's Guice injector can inject it into transport actions like {@code
14+
* TransportPPLQueryAction}.
15+
*/
16+
public record EngineExtensionsHolder(List<ExecutionEngine> engines) {
17+
public EngineExtensionsHolder(List<ExecutionEngine> engines) {
18+
this.engines = engines != null ? List.copyOf(engines) : List.of();
19+
}
20+
}

plugin/src/main/java/org/opensearch/sql/plugin/transport/TransportPPLQueryAction.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.opensearch.sql.monitor.profile.QueryProfiling;
3737
import org.opensearch.sql.opensearch.executor.OpenSearchQueryManager;
3838
import org.opensearch.sql.opensearch.setting.OpenSearchSettings;
39+
import org.opensearch.sql.plugin.config.EngineExtensionsHolder;
3940
import org.opensearch.sql.plugin.config.OpenSearchPluginModule;
4041
import org.opensearch.sql.plugin.rest.AnalyticsExecutorHolder;
4142
import org.opensearch.sql.plugin.rest.RestUnifiedQueryAction;
@@ -76,13 +77,14 @@ public TransportPPLQueryAction(
7677
NodeClient client,
7778
ClusterService clusterService,
7879
DataSourceServiceImpl dataSourceService,
79-
org.opensearch.common.settings.Settings clusterSettings) {
80+
org.opensearch.common.settings.Settings clusterSettings,
81+
EngineExtensionsHolder extensionsHolder) {
8082
super(PPLQueryAction.NAME, transportService, actionFilters, TransportPPLQueryRequest::new);
8183
this.clientRef = client;
8284
this.clusterServiceRef = clusterService;
8385

8486
ModulesBuilder modules = new ModulesBuilder();
85-
modules.add(new OpenSearchPluginModule());
87+
modules.add(new OpenSearchPluginModule(extensionsHolder.engines()));
8688
org.opensearch.sql.common.setting.Settings pluginSettings =
8789
new OpenSearchSettings(clusterService.getClusterSettings());
8890
this.pluginSettingsRef = pluginSettings;

0 commit comments

Comments
 (0)