PDGGK opened a new pull request, #116:
URL: https://github.com/apache/iotdb-extras/pull/116

   ## Problem
   
   The milliseconds aggregation path projects the numeric aggregate over a 
`COALESCE` expression:
   
   ```sql
   SELECT date_bin(<interval>ms, time, <startTs>) AS bucket_ts,
          MAX(COALESCE(double_v, CAST(long_v AS DOUBLE))) AS agg_num,
          ...
   FROM telemetry
   WHERE <identity predicates> AND time >= <start> AND time < <end>
   GROUP BY 1
   ```
   
   IoTDB's grouped max accumulator seeds FLOAT/DOUBLE state with 
`Float.MIN_VALUE` / `Double.MIN_VALUE` — the smallest *positive* values, not 
the most negative ones — and only marks a group initialized when `value >= 
state`. A bucket whose numeric maximum is zero or negative therefore never sets 
the flag and comes back as `NULL` (apache/iotdb#18300, fixed upstream after 
2.0.10).
   
   `aggregatedEntry` reads a NULL numeric aggregate as "this bucket has no 
value" and returns `null`, and `readMillisecondsAggregatedQuery` skips such 
buckets. So a `MAX` downsampling query over telemetry that is always zero or 
negative — a sub-zero temperature sensor, a gauge that sits at 0 — silently 
returned *fewer points*, with no error raised anywhere.
   
   Verified against the released `apache/iotdb:2.0.8` and `apache/iotdb:2.0.10` 
standalone images: a bucket of `-5.0, -3.0` and a bucket of `0.0, 0.0` both 
return `agg_num = NULL`, while a positive bucket is correct.
   
   Scope of the problem, also verified on both images:
   
   - `MIN`, `AVG`, `SUM` and `COUNT` are unaffected.
   - The calendar path is unaffected — it issues one bounded aggregate per 
bucket with no `GROUP BY`, and the non-grouped accumulator seeds correctly.
   - A long-only bucket is unaffected: it reads the direct `MAX(long_v)` 
channel, whose `LongBigArray` seeds with the true `Long.MIN_VALUE`.
   - A mixed long+double bucket *is* affected, because it reads the numeric 
channel.
   
   ## Fix
   
   Project `-MIN(-x)` instead of `MAX(x)` for the numeric channel. The grouped 
min accumulator seeds with `MAX_VALUE` and is not affected, and IEEE-754 
negation is exact, so this returns the same value as `MAX(x)` on servers with 
and without the upstream fix, with no extra query. The long and string channels 
seed correctly and keep using `MAX`.
   
   ## Tests
   
   Two integration tests against a real IoTDB container:
   
   - `maxKeepsBucketsWhoseValuesAreAllNonPositiveAgainstRealIoTDB` — buckets of 
all-negative and all-zero doubles keep their `MAX` (and `MIN` is unchanged).
   - `maxOverNonPositiveLongOnlyAndMixedBucketsKeepsResultTypeAgainstRealIoTDB` 
— covers the long-only channel and the mixed promotion, since they take 
different paths.
   
   Both fail on the previous projection with `bucket count expected: <2> but 
was: <0>` and `<1>` respectively — the buckets disappear — and pass with the 
fix. The existing aggregation coverage only ever used positive doubles, which 
is why this was not caught earlier.
   
   Full module build is green: 190 unit tests and 54 container integration 
tests.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to