microsoft / Kusto-Query-Language

Kusto Query Language is a simple and productive language for querying Big Data.
Apache License 2.0
510 stars 97 forks source link

Range operator does not correctly infer type when range expression is DateTime stepping by TimeSpan #134

Closed NeilMacMullen closed 1 month ago

NeilMacMullen commented 5 months ago

The range operator normally manages to infer the correct type for the output variable but fails in the specific case where a DateTime is stepped by a TimeSpan...

Here's a typical parse tree for long. The RangeOperator has correctly inferred that 'i' is long.

var query = @"range i from 1 to 100 step 1 | extend t=i";

QueryBlock: range i from 1 to 100 step 1 | extend t=i: 
 List: range i from 1 to 100 step 1 | extend t=i: 
  SeparatedElement: range i from 1 to 100 step 1 | extend t=i: 
   ExpressionStatement: range i from 1 to 100 step 1 | extend t=i: 
    PipeExpression: range i from 1 to 100 step 1 | extend t=i: (i: long, t: long)
     RangeOperator: range i from 1 to 100 step 1: (i: long)
      NameDeclaration: i: 
       TokenName: i: 
      LongLiteralExpression: 1: long
      LongLiteralExpression: 100: long
      LongLiteralExpression: 1: long
     ExtendOperator: extend t=i: (i: long, t: long)
      List: t=i: 
       SeparatedElement: t=i: 
        SimpleNamedExpression: t=i: long
         NameDeclaration: t: long
          TokenName: t: 
         NameReference: i: long
          TokenName: i: 

Here's an equivalent tree for range of DateTime stepped by TimeSpan. 'i' has been inferred to be of unknown type here even though it should be clear that it is DateTime.

var query = @"range i from datetime(2023-01-01) to datetime(2023-01-10) step 1d | extend t=i";

QueryBlock: range i from datetime(2023-01-01) to datetime(2023-01-10) step 1d | extend t=i: 
 List: range i from datetime(2023-01-01) to datetime(2023-01-10) step 1d | extend t=i: 
  SeparatedElement: range i from datetime(2023-01-01) to datetime(2023-01-10) step 1d | extend t=i: 
   ExpressionStatement: range i from datetime(2023-01-01) to datetime(2023-01-10) step 1d | extend t=i: 
    PipeExpression: range i from datetime(2023-01-01) to datetime(2023-01-10) step 1d | extend t=i: (i: unknown, t: unknown)
     RangeOperator: range i from datetime(2023-01-01) to datetime(2023-01-10) step 1d: (i: unknown)
      NameDeclaration: i: 
       TokenName: i: 
      DateTimeLiteralExpression: datetime(2023-01-01): datetime
      DateTimeLiteralExpression: datetime(2023-01-10): datetime
      TimespanLiteralExpression: 1d: timespan
     ExtendOperator: extend t=i: (i: unknown, t: unknown)
      List: t=i: 
       SeparatedElement: t=i: 
        SimpleNamedExpression: t=i: unknown
         NameDeclaration: t: unknown
          TokenName: t: 
         NameReference: i: unknown
          TokenName: i: 

I'm assuming this is something to do with the inconsistency in 'from','to', and 'step' types since it does correctly infer the type when stepping TimeSpan by TimeSpan....

var query = @"range i from 1d to 10d step 1d | extend t=i";

QueryBlock: range i from 1d to 10d step 1d | extend t=i: 
 List: range i from 1d to 10d step 1d | extend t=i: 
  SeparatedElement: range i from 1d to 10d step 1d | extend t=i: 
   ExpressionStatement: range i from 1d to 10d step 1d | extend t=i: 
    PipeExpression: range i from 1d to 10d step 1d | extend t=i: (i: timespan, t: timespan)
     RangeOperator: range i from 1d to 10d step 1d: (i: timespan)
      NameDeclaration: i: 
       TokenName: i: 
      TimespanLiteralExpression: 1d: timespan
      TimespanLiteralExpression: 10d: timespan
      TimespanLiteralExpression: 1d: timespan
     ExtendOperator: extend t=i: (i: timespan, t: timespan)
      List: t=i: 
       SeparatedElement: t=i: 
        SimpleNamedExpression: t=i: timespan
         NameDeclaration: t: timespan
          TokenName: t: 
         NameReference: i: timespan
          TokenName: i: 
mattwar commented 1 month ago

This is fixed in 11.5.4