@@ -78,12 +78,14 @@ public String visitIndexPattern(List<EsqlBaseParser.IndexPatternContext> ctx) {
7878 ctx .forEach (c -> {
7979 String indexPattern = visitIndexString (c .indexString ());
8080 String clusterString = visitClusterString (c .clusterString ());
81- String assembledName = clusterString != null ? clusterString + REMOTE_CLUSTER_INDEX_SEPARATOR + indexPattern : indexPattern ;
8281 // At this point, we run 2 kinds of checks. The first check is to ensure that this string adheres to the valid
8382 // pattern format. The second check is to ensure that the parts of this string, i.e. the remote name, cluster name, and
8483 // other aspects of them are valid. There's no point in running the second check if the first one fails.
85- if (assembledName .codePoints ().filter (ch -> ch == REMOTE_CLUSTER_INDEX_SEPARATOR ).count () > 1 ) {
86- throw new ParsingException (source (c ), "More than 1 occurrence of index separator found in index pattern" );
84+ // Should clusterString be non-null, validateClusterString() handles the required validation. So for now, look only at
85+ // the indexPattern.
86+ var maxSeparators = clusterString == null ? 1 : 0 ;
87+ if (patternExceedsMaxIndexSeparators (indexPattern , maxSeparators )) {
88+ throw new ParsingException (source (c ), "Unexpected index separator in index pattern" );
8789 }
8890 // skip validating index on remote cluster, because the behavior of remote cluster is not consistent with local cluster
8991 // For example, invalid#index is an invalid index name, however FROM *:invalid#index does not return an error
@@ -93,7 +95,7 @@ public String visitIndexPattern(List<EsqlBaseParser.IndexPatternContext> ctx) {
9395 } else {
9496 validateClusterString (clusterString , c );
9597 }
96- patterns .add (assembledName );
98+ patterns .add (clusterString != null ? clusterString + REMOTE_CLUSTER_INDEX_SEPARATOR + indexPattern : indexPattern );
9799 });
98100 return Strings .collectionToDelimitedString (patterns , "," );
99101 }
@@ -145,4 +147,20 @@ private static void validateIndexPattern(String indexPattern, EsqlBaseParser.Ind
145147 private static String removeExclusion (String indexPattern ) {
146148 return indexPattern .charAt (0 ) == EXCLUSION .charAt (0 ) ? indexPattern .substring (1 ) : indexPattern ;
147149 }
150+
151+ private static boolean patternExceedsMaxIndexSeparators (String pattern , int maxAllowedSeparators ) {
152+ int seperatorsCount = 0 ;
153+ boolean inDateTime = false ;
154+ for (char ch : pattern .toCharArray ()) {
155+ if (ch == '<' ) {
156+ inDateTime = true ;
157+ } else if (ch == '>' ) {
158+ inDateTime = false ;
159+ } else if (ch == REMOTE_CLUSTER_INDEX_SEPARATOR && inDateTime == false ) {
160+ seperatorsCount ++;
161+ }
162+ }
163+
164+ return seperatorsCount > maxAllowedSeparators ;
165+ }
148166}
0 commit comments