in query/time_bucketizer.go [72:174]
func (qc *AQLQueryContext) buildTimeDimensionExpr(timeBucketizerString string, timeColumn expr.Expr) (expr.Expr, error) {
var bucketizerExpr expr.Expr
var err error
timeColumnWithOffsetExpr := timeColumn
// construct TimeSeriesBucketizer expr
if qc.timezoneTable.tableColumn != "" {
var timezoneTableID, timezoneColumnID int
timezoneColumn := fmt.Sprintf("%s.%s", qc.timezoneTable.tableAlias, qc.timezoneTable.tableColumn)
timezoneTableID = qc.TableIDByAlias[qc.timezoneTable.tableAlias]
timezoneColumnID = qc.TableScanners[timezoneTableID].Schema.ColumnIDs[qc.timezoneTable.tableColumn]
// expand ast by offsetting timezone column
timeColumnWithOffsetExpr = &expr.BinaryExpr{
Op: expr.CONVERT_TZ,
LHS: timeColumn,
RHS: &expr.VarRef{
Val: timezoneColumn,
TableID: timezoneTableID,
ColumnID: timezoneColumnID,
},
}
} else if qc.fixedTimezone.String() != time.UTC.String() {
_, fromOffset := qc.fromTime.Time.Zone()
_, toOffset := qc.toTime.Time.Zone()
if fromOffset != toOffset {
offsetDiff := fromOffset - toOffset
switchTs, err := utils.CalculateDSTSwitchTs(qc.fromTime.Time.Unix(), qc.toTime.Time.Unix(), qc.fixedTimezone)
if err != nil {
return nil, err
}
qc.dstswitch = switchTs
// simulate IF statement. sub ast: timeCol + fromOffset + (timeCol > switchTs) * offsetDiff
// where (timeCol > switchTs) will return 1 or 0
timeColumnWithOffsetExpr = &expr.BinaryExpr{
Op: expr.ADD,
LHS: timeColumn,
RHS: &expr.BinaryExpr{
Op: expr.ADD,
LHS: &expr.NumberLiteral{
Expr: strconv.Itoa(fromOffset),
Int: fromOffset,
ExprType: expr.Signed,
},
RHS: &expr.BinaryExpr{
Op: expr.MUL,
LHS: &expr.NumberLiteral{
Expr: strconv.Itoa(offsetDiff),
Int: offsetDiff,
ExprType: expr.Signed,
},
RHS: &expr.BinaryExpr{
Op: expr.GTE,
LHS: timeColumn,
RHS: &expr.NumberLiteral{
Expr: strconv.Itoa(int(switchTs)),
Int: int(switchTs),
},
ExprType: expr.Boolean,
},
ExprType: expr.Signed,
},
},
}
} else {
timeColumnWithOffsetExpr = &expr.BinaryExpr{
Op: expr.CONVERT_TZ,
LHS: timeColumn,
RHS: &expr.NumberLiteral{
Expr: strconv.Itoa(fromOffset),
Int: fromOffset,
},
}
}
}
bucketizerExpr, err = parseRecurringTimeBucketizer(timeBucketizerString, timeColumnWithOffsetExpr)
if err != nil || bucketizerExpr != nil {
return bucketizerExpr, err
}
if bucketizerExpr = parseIrregularTimeBucketizer(timeBucketizerString, timeColumnWithOffsetExpr); bucketizerExpr != nil {
return bucketizerExpr, nil
}
timeBucket, err := common.ParseRegularTimeBucketizer(timeBucketizerString)
if err != nil {
return nil, err
}
bucketInSeconds := timeBucket.Size * common.BucketSizeToseconds[timeBucket.Unit]
bucketizerExpr = &expr.BinaryExpr{
Op: expr.FLOOR,
LHS: timeColumnWithOffsetExpr,
RHS: &expr.NumberLiteral{
Expr: strconv.Itoa(bucketInSeconds),
Int: bucketInSeconds,
ExprType: expr.Unsigned,
},
}
return bucketizerExpr, nil
}