@@ -605,11 +605,6 @@ private void preAnalyzeLookupIndex(
605605 indexResolver .resolveIndices (
606606 EsqlCCSUtils .createQualifiedLookupIndexExpressionFromAvailableClusters (executionInfo , localPattern ),
607607 result .wildcardJoinIndices ().contains (localPattern ) ? IndexResolver .ALL_FIELDS : result .fieldNames ,
608- null ,
609- false ,
610- // Disable aggregate_metric_double and dense_vector until we get version checks in planning
611- false ,
612- false ,
613608 listener .map (indexResolution -> receiveLookupIndexResolution (result , localPattern , executionInfo , indexResolution ))
614609 );
615610 }
@@ -810,20 +805,34 @@ private void preAnalyzeMainIndices(
810805 QueryBuilder requestFilter ,
811806 ActionListener <PreAnalysisResult > listener
812807 ) {
813- EsqlCCSUtils .initCrossClusterState (
814- indicesExpressionGrouper ,
815- verifier .licenseState (),
816- preAnalysis .indexes ().keySet (),
817- executionInfo
818- );
819- // The main index pattern dictates on which nodes the query can be executed,
820- // so we use the minimum transport version from this field caps request.
821- forAll (
822- preAnalysis .indexes ().entrySet ().iterator (),
823- result ,
824- (entry , r , l ) -> preAnalyzeMainIndices (entry .getKey (), entry .getValue (), preAnalysis , executionInfo , r , requestFilter , l ),
825- listener
808+ assert ThreadPool .assertCurrentThreadPool (
809+ ThreadPool .Names .SEARCH ,
810+ ThreadPool .Names .SEARCH_COORDINATION ,
811+ ThreadPool .Names .SYSTEM_READ
826812 );
813+ if (crossProjectModeDecider .crossProjectEnabled () == false ) {
814+ EsqlCCSUtils .initCrossClusterState (
815+ indicesExpressionGrouper ,
816+ verifier .licenseState (),
817+ preAnalysis .indexes ().keySet (),
818+ executionInfo
819+ );
820+ // The main index pattern dictates on which nodes the query can be executed,
821+ // so we use the minimum transport version from this field caps request.
822+ forAll (
823+ preAnalysis .indexes ().entrySet ().iterator (),
824+ result ,
825+ (e , r , l ) -> preAnalyzeMainIndices (e .getKey (), e .getValue (), preAnalysis , executionInfo , r , requestFilter , l ),
826+ listener
827+ );
828+ } else {
829+ forAll (
830+ preAnalysis .indexes ().entrySet ().iterator (),
831+ result ,
832+ (e , r , l ) -> preAnalyzeFlatMainIndices (e .getKey (), e .getValue (), preAnalysis , executionInfo , r , requestFilter , l ),
833+ listener
834+ );
835+ }
827836 }
828837
829838 private void preAnalyzeMainIndices (
@@ -835,28 +844,14 @@ private void preAnalyzeMainIndices(
835844 QueryBuilder requestFilter ,
836845 ActionListener <PreAnalysisResult > listener
837846 ) {
838- assert ThreadPool .assertCurrentThreadPool (
839- ThreadPool .Names .SEARCH ,
840- ThreadPool .Names .SEARCH_COORDINATION ,
841- ThreadPool .Names .SYSTEM_READ
842- );
843847 if (executionInfo .clusterAliases ().isEmpty ()) {
844848 // return empty resolution if the expression is pure CCS and resolved no remote clusters (like no-such-cluster*:index)
845849 listener .onResponse (result .withIndices (indexPattern , IndexResolution .empty (indexPattern .indexPattern ())));
846850 } else {
847851 indexResolver .resolveIndicesVersioned (
848852 indexPattern .indexPattern (),
849853 result .fieldNames ,
850- // Maybe if no indices are returned, retry without index mode and provide a clearer error message.
851- switch (indexMode ) {
852- case IndexMode .TIME_SERIES -> {
853- var indexModeFilter = new TermQueryBuilder (IndexModeFieldMapper .NAME , IndexMode .TIME_SERIES .getName ());
854- yield requestFilter != null
855- ? new BoolQueryBuilder ().filter (requestFilter ).filter (indexModeFilter )
856- : indexModeFilter ;
857- }
858- default -> requestFilter ;
859- },
854+ createQueryFilter (indexMode , requestFilter ),
860855 indexMode == IndexMode .TIME_SERIES ,
861856 preAnalysis .useAggregateMetricDoubleWhenNotSupported (),
862857 preAnalysis .useDenseVectorWhenNotSupported (),
@@ -872,6 +867,43 @@ private void preAnalyzeMainIndices(
872867 }
873868 }
874869
870+ private void preAnalyzeFlatMainIndices (
871+ IndexPattern indexPattern ,
872+ IndexMode indexMode ,
873+ PreAnalyzer .PreAnalysis preAnalysis ,
874+ EsqlExecutionInfo executionInfo ,
875+ PreAnalysisResult result ,
876+ QueryBuilder requestFilter ,
877+ ActionListener <PreAnalysisResult > listener
878+ ) {
879+ indexResolver .resolveFlatWorldIndicesVersioned (
880+ indexPattern .indexPattern (),
881+ result .fieldNames ,
882+ createQueryFilter (indexMode , requestFilter ),
883+ indexMode == IndexMode .TIME_SERIES ,
884+ preAnalysis .useAggregateMetricDoubleWhenNotSupported (),
885+ preAnalysis .useDenseVectorWhenNotSupported (),
886+ listener .delegateFailureAndWrap ((l , indexResolution ) -> {
887+ EsqlCCSUtils .initCrossClusterState (indexResolution .inner ().get (), executionInfo );
888+ EsqlCCSUtils .updateExecutionInfoWithUnavailableClusters (executionInfo , indexResolution .inner ().failures ());
889+ l .onResponse (
890+ result .withIndices (indexPattern , indexResolution .inner ()).withMinimumTransportVersion (indexResolution .minimumVersion ())
891+ );
892+ })
893+ );
894+ }
895+
896+ private static QueryBuilder createQueryFilter (IndexMode indexMode , QueryBuilder requestFilter ) {
897+ // Maybe if no indices are returned, retry without index mode and provide a clearer error message.
898+ return switch (indexMode ) {
899+ case IndexMode .TIME_SERIES -> {
900+ var indexModeFilter = new TermQueryBuilder (IndexModeFieldMapper .NAME , IndexMode .TIME_SERIES .getName ());
901+ yield requestFilter != null ? new BoolQueryBuilder ().filter (requestFilter ).filter (indexModeFilter ) : indexModeFilter ;
902+ }
903+ default -> requestFilter ;
904+ };
905+ }
906+
875907 private void analyzeWithRetry (
876908 LogicalPlan parsed ,
877909 Configuration configuration ,
0 commit comments