Skip to content

Commit f02c936

Browse files
committed
added some comments
1 parent 48617d6 commit f02c936

File tree

1 file changed

+51
-45
lines changed

1 file changed

+51
-45
lines changed

vm/datemath.go

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,9 @@ func findDateMathFn(node expr.Node) BoundaryFns {
190190
// Only handle BETWEEN operator with specific node types
191191
if n.Operator.T == lex.TokenBetween && len(n.Args) == 3 {
192192
// Check if first arg is IdentityNode and other two are StringNodes
193-
_, isFirstIdentity := n.Args[0].(*expr.IdentityNode)
194-
_, isSecondString := n.Args[1].(*expr.StringNode)
195-
_, isThirdString := n.Args[2].(*expr.StringNode)
196-
197-
if isFirstIdentity && isSecondString && isThirdString {
198-
fns = append(fns, findBoundaryForBetween(n))
193+
fn := findBoundaryForBetween(n)
194+
if fn != nil {
195+
fns = append(fns, fn)
199196
return fns
200197
}
201198
}
@@ -222,67 +219,76 @@ func findDateMathFn(node expr.Node) BoundaryFns {
222219
return fns
223220
}
224221

225-
// Ct = Comparison time, left hand side of expression
226-
// Lb = Relative time result of Lower Bound Anchor Time offset by datemath "now-3d"
227-
// Ub = Relative time result of Upper Bound Anchor Time offset by datemath "now+3d"
228-
// Bt = Boundary time = calculated time at which expression will change boolean expression value
229-
// example: FILTER Ct BETWEEN Lb AND Ub
230-
// WHERE "now" = 01/22/2025 00:00:00
222+
// findBoundaryForBetween calculates the next time boundary for a BETWEEN expression
223+
// with date math boundaries. It handles expressions like:
224+
//
225+
// time_column BETWEEN "now-3d" AND "now+3d"
226+
//
227+
// The function returns a boundary function that:
228+
// 1. Evaluates the comparison time (Ct) against the window boundaries
229+
// 2. Determines when the expression's boolean value will change
230+
// 3. Returns the appropriate re-evaluation time
231231
//
232-
// "Lb" = 01/19/2025 00:00:00
233-
// "Ub" = 01/25/2025 00:00:00
232+
// Example:
234233
//
235-
// NOTE: When evaluating expressions like this, an entity "enters" the expression by passing the upper bound and sliding into the window
236-
// and "exits" the expression by passing the lower bound and sliding out of the window. Although the "Upper Bound" is after the "Lower Bound",
237-
// the order of entry and exit is reversed. This example should show how the entity appears to move backwards as the window moves forward.
238-
// Example timeline: Ct = 01/22/2025 00:00:00
239-
// Day 0: now = 01/22/2025 00:00:00 === Lb--Ct++Ub+++++++++
240-
// Day 1: now = 01/23/2025 00:00:00 === -Lb-Ct+++Ub++++++++
241-
// Day 2: now = 01/24/2025 00:00:00 === --LbCt++++Ub+++++++
242-
// Day 3: now = 01/25/2025 00:00:00 === ---CLtb+++++Ub+++++ Ct == Lb
243-
// Day 4: now = 01/26/2025 00:00:00 === ---CtLb++++++Ub++++
244-
// Day 5: now = 01/27/2025 00:00:00 === ---Ct-Lb++++++Ub+++
245-
// Day 6: now = 01/28/2025 00:00:00 === ---Ct--Lb++++++Ub++
246-
// Day 7: now = 01/29/2025 00:00:00 === ---Ct---Lb++++++Ub+
247-
// Day 8: now = 01/30/2025 00:00:00 === ---Ct----Lb++++++Ub
234+
// Input: time_column BETWEEN "now-3d" AND "now+3d"
235+
// When: now = 2025-01-22
236+
// Window: 2025-01-19 to 2025-01-25
248237
//
249-
// Notice how it appears as if the entity is moving backwards through the window as the window slides forward in relation to "now".
250-
// Ct = 01/01/2025 00:00:00
251-
// In this case the expression itself currently evaluates to false, and is already PRIOR to the lower bound.
252-
// As such it will always evaluate to false, so we can skip queueing for reevaluation.
253-
// // Ct = 01/30/2025 00:00:00
254-
// In this case the expression itself currently evaluates to false, and is AFTER of the prior to the upper bound.
255-
// The next evaluation time should be on the day the upper bound is reached. Queue for reevaluation at (Ct - 3d) [since the Ub is now+3d].
256-
// // Ct = 01/22/2025 00:00:00
257-
// In this case the expression itself currently evaluates to true, and is BETWEEN the lower and upper bounds.
258-
// The next evaluation time should be on the day the lower bound is reached. Queue for reevaluation at (Ct + 3d) [since the Lb is now-3d].
259-
// Notice that we are queuing for reevaluation based on the inverse of the corresponding bound's offset. This is made a bit easier if
260-
// the expression is a static date, rather than a relative one. As we can use that directly as the re-evaluation time.
238+
// If Ct = 2025-01-01 (left side of window):
239+
// - Expression is false
240+
// - Will always be false as window is moving forward
241+
// - Returns zero time (no re-evaluation needed)
242+
//
243+
// If Ct = 2025-01-30 (right side of window):
244+
// - Expression is false
245+
// - Will become true when window catches up (enter event)
246+
// - Returns re-evaluation time when this will enter the window
247+
//
248+
// If Ct = 2025-01-22 (inside window):
249+
// - Expression is true
250+
// - Will become false when Ct passes lower bound (exit event)
251+
// - Returns re-evaluation time when this will be exit the window
261252
func findBoundaryForBetween(n *expr.TriNode) func(d *DateConverter, ctx expr.EvalIncludeContext) {
253+
254+
// Check if first arg is IdentityNode and other two are StringNodes
255+
_, isFirstIdentity := n.Args[0].(*expr.IdentityNode)
256+
_, isSecondString := n.Args[1].(*expr.StringNode)
257+
_, isThirdString := n.Args[2].(*expr.StringNode)
258+
259+
if !isFirstIdentity || !isSecondString || !isThirdString {
260+
return nil
261+
}
262+
arg1, arg2, arg3 := n.Args[0], n.Args[1], n.Args[2]
263+
264+
// datemath only if both date args are relative to an anchor time like "now-1d"
265+
val2 := strings.ToLower(arg2.(*expr.StringNode).Text)
266+
val3 := strings.ToLower(arg3.(*expr.StringNode).Text)
267+
if !nowRegex.MatchString(val2) || !nowRegex.MatchString(val3) {
268+
return nil
269+
}
270+
262271
return func(d *DateConverter, ctx expr.EvalIncludeContext) {
263-
arg1, arg2, arg3 := n.Args[0], n.Args[1], n.Args[2]
264272

265273
lhv, ok := Eval(ctx, arg1)
266274
if !ok {
267275
return
268276
}
269277
ct, ok := value.ValueToTime(lhv)
270278
if !ok {
271-
// may be not a time field, so ignore doing any update
279+
d.err = fmt.Errorf("could not convert %T: %v to time.Time", lhv, lhv)
272280
return
273281
}
274282

275-
val2 := strings.ToLower(arg2.(*expr.StringNode).Text)
276283
date1, err := datemath.EvalAnchor(d.at, val2)
277284
if err != nil {
278-
// may be not a valid date expression, so ignore doing any update
285+
d.err = err
279286
return
280287
}
281288

282-
val3 := strings.ToLower(arg3.(*expr.StringNode).Text)
283289
date2, err := datemath.EvalAnchor(d.at, val3)
284290
if err != nil {
285-
// may be not a valid date expression, so ignore doing any update
291+
d.err = err
286292
return
287293
}
288294

0 commit comments

Comments
 (0)