DaZuiZui commented on issue #18428:
URL: https://github.com/apache/iotdb/issues/18428#issuecomment-5235636695

   ## Proposed functional definition and implementation direction
   
   After reviewing the latest master, I think calendar duration must be treated 
as first-class CQ metadata throughout parsing, RPC, persistence, recovery, and 
scheduling. Changing only parseResampleClause or converting a month against the 
creation time would still drift later.
   
   ### 1. User-visible syntax and supported values
   
   The existing CQ syntax remains unchanged:
   
       CREATE [CONTINUOUS QUERY | CQ] <cq_id>
       [RESAMPLE
         [EVERY <duration>]
         [BOUNDARY <time_value>]
         [RANGE <start_offset> [, <end_offset>]]
       ]
       [TIMEOUT POLICY {BLOCKED | DISCARD}]
       BEGIN
         <select_into_statement>
       END
   
   Proposed duration units:
   
   - Calendar units: y/year and mo/month
   - Existing fixed units: w, d, h, m, s, ms, us, ns
   - Compound values remain supported, for example 1y2mo3d
   - 1y is normalized to 12 calendar months
   - d and w remain fixed 24-hour/7-day durations; only mo/y have calendar 
semantics
   - This feature does not change the data types, aggregations, or SELECT INTO 
rules supported by the CQ query body
   
   Logically, a duration is represented by an integer calendar-month part plus 
a fixed-tick part in the configured timestamp precision.
   
   If EVERY is omitted, it inherits the complete GROUP BY TIME duration. 
Therefore, GROUP BY(1mo) must yield a calendar-month EVERY, not 30 days. If 
RANGE is omitted, its defaults remain startOffset = EVERY and endOffset = 0.
   
   ### 2. Calendar scheduling semantics
   
   All calendar arithmetic must use the session zone captured when the CQ is 
created and persisted with the CQ.
   
   For boundary B, interval E, CQ zone Z, and occurrence index n:
   
       executionTime(n) = calendarApply(B, n * E, Z)
   
   Each occurrence must be calculated from the original boundary. It must not 
repeatedly call previousExecutionTime.plusMonths(1), because that would drift:
   
       Wrong:   Jan-31 -> Feb-29 -> Mar-29
       Correct: Jan-31 -> Feb-29 -> Mar-31
   
   Month-end uses standard last-valid-day clamping:
   
       2023-01-31 + 1mo = 2023-02-28
       2024-01-31 + 1mo = 2024-02-29
       2020-02-29 + 1y  = 2021-02-28
       2020-02-29 + 4y  = 2024-02-29
   
   To preserve the currently documented boundary formula and avoid 
non-invertible month subtraction, I recommend calculating RANGE endpoints in 
duration-vector space:
   
       startTime(n) = calendarApply(B, n * E - startOffset, Z)
       endTime(n)   = calendarApply(B, n * E - endOffset, Z)
   
   This makes EVERY 1mo RANGE 1mo produce contiguous windows even for a Jan-31 
or Feb-29 anchor.
   
   For timeout policies:
   
   - BLOCKED executes every occurrence in order, even when late. Its query 
window is based on the scheduled occurrence time, not the actual wall-clock 
start time.
   - DISCARD skips missed occurrences and jumps directly to the first valid 
occurrence not earlier than the current time.
   - Calendar lookup should use an estimate plus correction or binary search, 
not a linear loop from 1970.
   
   ### 3. Validation and compatibility
   
   The existing positive-value rules remain: EVERY > 0, startOffset > 0, 
endOffset >= 0, startOffset > endOffset, and the current startOffset >= EVERY 
constraint.
   
   Calendar and fixed durations do not have a total ordering: 1mo may be 
shorter or longer than 30d. Such comparisons must not flatten months to 30 
days. Ambiguous mixed comparisons should either use conservative min/max bounds 
or be rejected with a clear semantic error.
   
   For compatibility, I suggest:
   
   - Add optional structured duration fields to TCreateCQReq; keep the existing 
i64 fields for legacy readers
   - New ConfigNodes prefer the structured values; old requests become 
fixed-only durations
   - Version the CQInfo snapshot format and load old snapshots as 
fixed-duration CQs
   - Do not silently migrate existing persisted 1mo/1y CQs by reparsing their 
saved SQL; users can recreate them to opt into calendar semantics
   - Enable creation of calendar CQs only after all ConfigNodes are upgraded
   
   The DataNode execution RPC can continue receiving concrete 
startTime/endTime; the main execution engine does not need calendar-duration 
awareness. Its timeout should use the actual distance to the next occurrence 
rather than a 30-day approximation.
   
   ### 4. Two semantics to confirm before implementation
   
   1. When a calendar EVERY omits BOUNDARY, should it align to local calendar 
boundaries? My recommendation is to use 1970-01-01 00:00:00 in the persisted CQ 
zone, while an explicit BOUNDARY 0 continues to mean the Unix epoch instant. 
This requires preserving whether BOUNDARY was explicitly specified.
   2. Can RANGE use the anchored vector formula above? It preserves the 
existing documented formula and makes EVERY == RANGE contiguous at month-end, 
while direct subtraction from a clamped execution timestamp does not.
   
   Suggested tests should cover explicit and inherited 1mo/1y, Jan-31, leap 
day, DST zones, ms/us/ns precision, BLOCKED/DISCARD catch-up, leader recovery, 
procedure/plan serialization, and legacy CQ snapshots.
   


-- 
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