@@ -337,9 +337,8 @@ func TestWriteTimeTag(t *testing.T) {
337337 time .Unix (1 , 2 ),
338338 )
339339
340- if err := sh .WritePoints ([]models.Point {pt }, tsdb .NoopStatsTracker ()); err != nil {
341- t .Fatalf ("unexpected error: %v" , err )
342- }
340+ err := sh .WritePoints ([]models.Point {pt }, tsdb .NoopStatsTracker ())
341+ require .Error (t , err , "expected partial write error" )
343342
344343 mf := sh .MeasurementFields ([]byte ("cpu" ))
345344 if mf == nil {
@@ -435,6 +434,81 @@ func TestShardWriteAddNewField(t *testing.T) {
435434 }
436435}
437436
437+ func TestShardWriteDropField (t * testing.T ) {
438+ tmpDir , _ := os .MkdirTemp ("" , "shard_test" )
439+ defer func (path string ) {
440+ err := os .RemoveAll (path )
441+ require .NoError (t , err , "error removing temp dir" )
442+ }(tmpDir )
443+
444+ tmpShard := filepath .Join (tmpDir , "shard" )
445+ tmpWal := filepath .Join (tmpDir , "wal" )
446+
447+ sfile := MustOpenSeriesFile ()
448+ defer func (sfile * SeriesFile ) {
449+ err := sfile .Close ()
450+ require .NoError (t , err , "error closing series file" )
451+ }(sfile )
452+
453+ opts := tsdb .NewEngineOptions ()
454+ opts .Config .WALDir = filepath .Join (tmpDir , "wal" )
455+ opts .InmemIndex = inmem .NewIndex (filepath .Base (tmpDir ), sfile .SeriesFile )
456+
457+ sh := tsdb .NewShard (1 , tmpShard , tmpWal , sfile .SeriesFile , opts )
458+ err := sh .Open ()
459+ require .NoError (t , err , "error opening shard" )
460+
461+ defer func (sh * tsdb.Shard ) {
462+ err := sh .Close ()
463+ require .NoError (t , err , "error closing shard" )
464+ }(sh )
465+
466+ pt := models .MustNewPoint (
467+ "cpu" ,
468+ models .NewTags (map [string ]string {"host" : "server" }),
469+ map [string ]interface {}{"value" : 1.0 },
470+ time .Unix (1 , 2 ),
471+ )
472+
473+ err = sh .WritePoints ([]models.Point {pt }, tsdb .NoopStatsTracker ())
474+ require .NoError (t , err , "error writing point" )
475+
476+ pt = models .MustNewPoint (
477+ "cpu" ,
478+ models .NewTags (map [string ]string {"host" : "server" }),
479+ map [string ]interface {}{"value" : 1.0 , "value2" : 2.0 , "time" : time .Now ().Unix ()},
480+ time .Unix (1 , 2 ),
481+ )
482+
483+ err = sh .WritePoints ([]models.Point {pt }, tsdb .NoopStatsTracker ())
484+ require .Error (t , err , "writing point should error with partial write" )
485+ require .ErrorContains (t , err , "partial write: invalid field name: input field \" time\" on measurement \" cpu\" is invalid. Field \" time\" has been stripped from point. dropped=0 for database:" )
486+
487+ // Point should not be written and fully dropped due to having a single "time" field
488+ pt = models .MustNewPoint (
489+ "cpu" ,
490+ models .NewTags (map [string ]string {"host" : "server" }),
491+ map [string ]interface {}{"time" : time .Now ().Unix ()},
492+ time .Unix (1 , 2 ),
493+ )
494+
495+ err = sh .WritePoints ([]models.Point {pt }, tsdb .NoopStatsTracker ())
496+ require .Error (t , err , "writing point should error with partial write" )
497+ require .ErrorContains (t , err , "partial write: invalid field name: input field \" time\" on measurement \" cpu\" is invalid dropped=1 for database:" )
498+
499+ require .Equal (t , int64 (1 ), sh .SeriesN (), "wrong number of series" )
500+ stats := sh .Statistics (nil )
501+ require .GreaterOrEqual (t , len (stats ), 1 , "wrong number of stats" )
502+ values := stats [0 ].Values
503+ pointsOK := values ["writePointsOk" ].(int64 )
504+
505+ require .Equal (t , int64 (2 ), pointsOK , "should have written 2 points successfully" )
506+
507+ mf := sh .MeasurementFields ([]byte ("cpu" ))
508+ require .NotNil (t , mf , "measurement fields should not be nil" )
509+ require .Equal (t , 2 , mf .FieldN (), "measurement fields should have 2 values" )
510+ }
511+
438512// Tests concurrently writing to the same shard with different field types which
439513// can trigger a panic when the shard is snapshotted to TSM files.
440514func TestShard_WritePoints_FieldConflictConcurrent (t * testing.T ) {
0 commit comments