13
13
import org .elasticsearch .cluster .metadata .MappingMetadata ;
14
14
import org .elasticsearch .common .TriFunction ;
15
15
import org .elasticsearch .common .time .DateFormatter ;
16
+ import org .elasticsearch .common .time .DateUtils ;
16
17
import org .elasticsearch .common .time .LegacyFormatNames ;
17
18
import org .elasticsearch .core .Strings ;
18
19
import org .elasticsearch .index .IndexModule ;
@@ -99,6 +100,21 @@ private DeprecationIssue oldIndicesCheck(
99
100
IndexVersion currentCompatibilityVersion = indexMetadata .getCompatibilityVersion ();
100
101
// We intentionally exclude indices that are in data streams because they will be picked up by DataStreamDeprecationChecks
101
102
if (DeprecatedIndexPredicate .reindexRequired (indexMetadata , false , false ) && isNotDataStreamIndex (indexMetadata , clusterState )) {
103
+ List <String > cldrIncompatibleFieldMappings = new ArrayList <>();
104
+ fieldLevelMappingIssue (
105
+ indexMetadata ,
106
+ (mappingMetadata , sourceAsMap ) -> cldrIncompatibleFieldMappings .addAll (
107
+ findInPropertiesRecursively (
108
+ mappingMetadata .type (),
109
+ sourceAsMap ,
110
+ this ::isDateFieldWithCompatFormatPattern ,
111
+ this ::cldrIncompatibleFormatPattern ,
112
+ "" ,
113
+ ""
114
+ )
115
+ )
116
+ );
117
+
102
118
var transforms = transformIdsForIndex (indexMetadata , indexToTransformIds );
103
119
if (transforms .isEmpty () == false ) {
104
120
return new DeprecationIssue (
@@ -116,6 +132,17 @@ private DeprecationIssue oldIndicesCheck(
116
132
false ,
117
133
Map .of ("reindex_required" , true , "transform_ids" , transforms )
118
134
);
135
+ } else if (cldrIncompatibleFieldMappings .isEmpty () == false ) {
136
+ return new DeprecationIssue (
137
+ DeprecationIssue .Level .CRITICAL ,
138
+ "Field mappings with incompatible date format patterns in old index" ,
139
+ "https://www.elastic.co/blog/locale-changes-elasticsearch-8-16-jdk-23" ,
140
+ "The index was created before 8.0 and contains mappings that must be reindexed due to locale changes in 8.16+. "
141
+ + "Manual reindexing is required. "
142
+ + String .join (", " , cldrIncompatibleFieldMappings ),
143
+ false ,
144
+ null
145
+ );
119
146
} else {
120
147
return new DeprecationIssue (
121
148
DeprecationIssue .Level .CRITICAL ,
@@ -396,6 +423,24 @@ private DeprecationIssue deprecatedCamelCasePattern(
396
423
return null ;
397
424
}
398
425
426
+ private boolean isDateFieldWithCompatFormatPattern (Map <?, ?> property ) {
427
+ if ("date" .equals (property .get ("type" )) && property .containsKey ("format" )) {
428
+ String [] patterns = DateFormatter .splitCombinedPatterns ((String ) property .get ("format" ));
429
+ for (String pattern : patterns ) {
430
+ if (DateUtils .containsCompatOnlyDateFormat (pattern )) {
431
+ return true ;
432
+ }
433
+ }
434
+ }
435
+ return false ;
436
+ }
437
+
438
+ private String cldrIncompatibleFormatPattern (String type , Map .Entry <?, ?> entry ) {
439
+ Map <?, ?> value = (Map <?, ?>) entry .getValue ();
440
+ final String formatFieldValue = (String ) value .get ("format" );
441
+ return "Field [" + entry .getKey () + "] with format pattern [" + formatFieldValue + "]." ;
442
+ }
443
+
399
444
private boolean isDateFieldWithCamelCasePattern (Map <?, ?> property ) {
400
445
if ("date" .equals (property .get ("type" )) && property .containsKey ("format" )) {
401
446
String [] patterns = DateFormatter .splitCombinedPatterns ((String ) property .get ("format" ));
0 commit comments