Pritam Kumar created FLINK-41026:
------------------------------------

             Summary: [format/avro] Convert timestamps above precision 3 as 
microseconds in both directions
                 Key: FLINK-41026
                 URL: https://issues.apache.org/jira/browse/FLINK-41026
             Project: Flink
          Issue Type: Bug
          Components: Formats (JSON, Avro, Parquet, ORC, SequenceFile)
            Reporter: Pritam Kumar


h2. What

{{AvroToRowDataConverters}} and {{RowDataToAvroConverters}} now follow the unit 
{{AvroSchemaConverter}} declares for a timestamp column: microseconds when the 
mapping is not legacy and the precision is above 3, milliseconds otherwise.
h2. Why

For {{TIMESTAMP(4..6)}} and {{TIMESTAMP_LTZ(4..6)}} the schema says 
{{local-timestamp-micros}} / {{{}timestamp-micros{}}}, but:
 * the reader took every {{long}} as milliseconds, so a microsecond value was 
read a thousand times too large;
 * an {{Instant}} went through {{{}toEpochMilli(){}}}, which drops the 
sub-millisecond digits;
 * the writer wrote every timestamp as epoch milliseconds, also into a field 
declared as microseconds.

Reading a long as microseconds with a truncating {{/}} and {{%}} would also 
fail for a negative value that is not a whole millisecond (for example 
{{{}-86400000001{}}}, 1969-12-30T23:59:59.999999Z): the nanosecond part comes 
out negative and {{TimestampData.fromEpochMillis}} throws an 
{{IllegalArgumentException}} without a message. This is how a job reading such 
a record from Kafka ended up restarting forever; it was found by comparing a 
Flink sink with a Kafka Connect sink on the same records.
h2. Change
 * Reader: a {{long}} is split with {{Math.floorDiv}} / {{Math.floorMod}} when 
the column is a microsecond one; an {{Instant}} goes through 
{{TimestampData.fromInstant}} there; milliseconds columns and the legacy 
mapping are untouched.
 * Writer: a microsecond column is written as microseconds, computed from the 
seconds and the (never negative) nanosecond part. {{ChronoUnit.MICROS.between}} 
is not used because it counts nanoseconds on the way and overflows outside the 
years 1678 to 2262.
 * {{{}TIME{}}}: a {{long}} is accepted (a {{time-micros}} that the Avro reader 
gave without a logical type conversion). {{RowData}} stores a TIME as an int of 
milliseconds, so the microseconds are dropped there; this is stated in the code.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to