@@ -916,6 +916,30 @@ Status RowTransaction::DeleteFromColumn(
916916 return maybe_column_family.status ();
917917 }
918918
919+ // We need to check if the given timerange is empty or reversed, but
920+ // only up to the server's time accuracy (in our case, milliseconds)
921+ // - For example a time range of [1000, 1200] would be empty.
922+ if (delete_from_column.has_time_range ()) {
923+ auto start = std::chrono::duration_cast<std::chrono::milliseconds>(
924+ std::chrono::microseconds (
925+ delete_from_column.time_range ().start_timestamp_micros ()));
926+ auto end = std::chrono::duration_cast<std::chrono::milliseconds>(
927+ std::chrono::microseconds (
928+ delete_from_column.time_range ().end_timestamp_micros ()));
929+
930+ // An end timestamp micros of 0 is to be interpreted as infinity,
931+ // so we allow that.
932+ if (end <= start &&
933+ delete_from_column.time_range ().end_timestamp_micros () != 0 ) {
934+ return InvalidArgumentError (
935+ " empty or reversed time range: the end timestamp must be more than "
936+ " the start timestamp when they are truncated to the server's time "
937+ " precision (milliseconds)" ,
938+ GCP_ERROR_INFO ().WithMetadata (" delete_from_column proto" ,
939+ delete_from_column.DebugString ()));
940+ }
941+ }
942+
919943 auto & column_family = maybe_column_family->get ();
920944
921945 auto deleted_cells = column_family.DeleteColumn (
0 commit comments