15
15
import org .elasticsearch .common .time .DateUtils ;
16
16
import org .elasticsearch .core .CheckedConsumer ;
17
17
import org .elasticsearch .core .Strings ;
18
- import org .elasticsearch .core .Tuple ;
19
18
import org .elasticsearch .index .IndexVersion ;
20
19
import org .elasticsearch .index .IndexVersions ;
21
20
import org .elasticsearch .index .mapper .DateFieldMapper .DateFieldType ;
35
34
import java .util .Comparator ;
36
35
import java .util .List ;
37
36
import java .util .function .Function ;
37
+ import java .util .stream .Stream ;
38
38
39
39
import static org .elasticsearch .index .mapper .DateFieldMapper .DEFAULT_DATE_TIME_FORMATTER ;
40
40
import static org .hamcrest .Matchers .containsString ;
@@ -152,7 +152,13 @@ protected List<ExampleMalformedValue> exampleMalformedValues() {
152
152
return List .of (
153
153
exampleMalformedValue ("2016-03-99" ).mapping (mappingWithFormat ("strict_date_optional_time||epoch_millis" ))
154
154
.errorMatches ("failed to parse date field [2016-03-99] with format [strict_date_optional_time||epoch_millis]" ),
155
- exampleMalformedValue ("-522000000" ).mapping (mappingWithFormat ("date_optional_time" )).errorMatches ("long overflow" )
155
+ exampleMalformedValue ("-522000000" ).mapping (mappingWithFormat ("date_optional_time" )).errorMatches ("long overflow" ),
156
+ exampleMalformedValue ("2020" ).mapping (mappingWithFormat ("strict_date" ))
157
+ .errorMatches ("failed to parse date field [2020] with format [strict_date]" ),
158
+ exampleMalformedValue ("hello world" ).mapping (mappingWithFormat ("strict_date_optional_time" ))
159
+ .errorMatches ("failed to parse date field [hello world]" ),
160
+ exampleMalformedValue ("true" ).mapping (mappingWithFormat ("strict_date_optional_time" ))
161
+ .errorMatches ("failed to parse date field [true]" )
156
162
);
157
163
}
158
164
@@ -561,7 +567,6 @@ public void testScriptAndPrecludedParameters() {
561
567
562
568
@ Override
563
569
protected SyntheticSourceSupport syntheticSourceSupport (boolean ignoreMalformed ) {
564
- assumeFalse ("synthetic _source for date and date_millis doesn't support ignore_malformed" , ignoreMalformed );
565
570
return new SyntheticSourceSupport () {
566
571
private final DateFieldMapper .Resolution resolution = randomFrom (DateFieldMapper .Resolution .values ());
567
572
private final Object nullValue = usually ()
@@ -577,36 +582,62 @@ protected SyntheticSourceSupport syntheticSourceSupport(boolean ignoreMalformed)
577
582
@ Override
578
583
public SyntheticSourceExample example (int maxValues ) {
579
584
if (randomBoolean ()) {
580
- Tuple <Object , String > v = generateValue ();
585
+ Value v = generateValue ();
586
+ if (v .malformedOutput != null ) {
587
+ return new SyntheticSourceExample (v .input , v .malformedOutput , null , this ::mapping );
588
+ }
589
+
581
590
return new SyntheticSourceExample (
582
- v .v1 () ,
583
- v .v2 () ,
584
- resolution .convert (Instant .from (formatter .parse (v .v2 () ))),
591
+ v .input ,
592
+ v .output ,
593
+ resolution .convert (Instant .from (formatter .parse (v .output ))),
585
594
this ::mapping
586
595
);
587
596
}
588
- List <Tuple <Object , String >> values = randomList (1 , maxValues , this ::generateValue );
589
- List <Object > in = values .stream ().map (Tuple ::v1 ).toList ();
590
- List <String > outList = values .stream ()
597
+
598
+ List <Value > values = randomList (1 , maxValues , this ::generateValue );
599
+ List <Object > in = values .stream ().map (Value ::input ).toList ();
600
+
601
+ List <String > outputFromDocValues = values .stream ()
602
+ .filter (v -> v .malformedOutput == null )
591
603
.sorted (
592
- Comparator .comparing (v -> Instant .from (formatter .parse (v .v1 () == null ? nullValue .toString () : v .v1 ().toString ())))
604
+ Comparator .comparing (
605
+ v -> Instant .from (formatter .parse (v .input == null ? nullValue .toString () : v .input .toString ()))
606
+ )
593
607
)
594
- .map (Tuple :: v2 )
608
+ .map (Value :: output )
595
609
.toList ();
610
+
611
+ Stream <Object > malformedOutput = values .stream ().filter (v -> v .malformedOutput != null ).map (Value ::malformedOutput );
612
+
613
+ // Malformed values are always last in the implementation.
614
+ List <Object > outList = Stream .concat (outputFromDocValues .stream (), malformedOutput ).toList ();
596
615
Object out = outList .size () == 1 ? outList .get (0 ) : outList ;
597
616
598
- List <Long > outBlockList = outList .stream ().map (v -> resolution .convert (Instant .from (formatter .parse (v )))).toList ();
617
+ List <Long > outBlockList = outputFromDocValues .stream ()
618
+ .map (v -> resolution .convert (Instant .from (formatter .parse (v ))))
619
+ .toList ();
599
620
Object outBlock = outBlockList .size () == 1 ? outBlockList .get (0 ) : outBlockList ;
600
621
return new SyntheticSourceExample (in , out , outBlock , this ::mapping );
601
622
}
602
623
603
- private Tuple <Object , String > generateValue () {
624
+ private record Value (Object input , String output , Object malformedOutput ) {}
625
+
626
+ private Value generateValue () {
604
627
if (nullValue != null && randomBoolean ()) {
605
- return Tuple .tuple (null , outValue (nullValue ));
628
+ return new Value (null , outValue (nullValue ), null );
629
+ }
630
+ // Different malformed values are tested in #exampleMalformedValues().
631
+ // Here we only verify behavior of arrays that contain malformed
632
+ // values since there are modifications specific to synthetic source.
633
+ if (ignoreMalformed && randomBoolean ()) {
634
+ var malformedInput = randomAlphaOfLengthBetween (1 , 10 );
635
+ return new Value (malformedInput , null , malformedInput );
606
636
}
637
+
607
638
Object in = randomValue ();
608
639
String out = outValue (in );
609
- return Tuple . tuple (in , out );
640
+ return new Value (in , out , null );
610
641
}
611
642
612
643
private Object randomValue () {
@@ -637,6 +668,9 @@ private void mapping(XContentBuilder b) throws IOException {
637
668
if (nullValue != null ) {
638
669
b .field ("null_value" , nullValue );
639
670
}
671
+ if (ignoreMalformed ) {
672
+ b .field ("ignore_malformed" , true );
673
+ }
640
674
}
641
675
642
676
@ Override
@@ -653,16 +687,6 @@ public List<SyntheticSourceInvalidExample> invalidExample() throws IOException {
653
687
b -> b .field ("type" , fieldType ).field ("doc_values" , false )
654
688
)
655
689
);
656
- examples .add (
657
- new SyntheticSourceInvalidExample (
658
- equalTo (
659
- "field [field] of type ["
660
- + fieldType
661
- + "] doesn't support synthetic source because it ignores malformed dates"
662
- ),
663
- b -> b .field ("type" , fieldType ).field ("ignore_malformed" , true )
664
- )
665
- );
666
690
}
667
691
return examples ;
668
692
}
0 commit comments