1- import  {  chSql ,  parameterizedQueryToSql  }  from  '@/clickhouse' ; 
1+ import  {  chSql ,  ColumnMeta ,   parameterizedQueryToSql  }  from  '@/clickhouse' ; 
22import  {  Metadata  }  from  '@/metadata' ; 
33import  { 
44  ChartConfigWithOptDateRange , 
55  DisplayType , 
66  MetricsDataType , 
77}  from  '@/types' ; 
88
9- import  {  renderChartConfig  }  from  '../renderChartConfig' ; 
9+ import  {  renderChartConfig ,   timeFilterExpr  }  from  '../renderChartConfig' ; 
1010
1111describe ( 'renderChartConfig' ,  ( )  =>  { 
12-   let  mockMetadata : Metadata ; 
12+   let  mockMetadata : jest . Mocked < Metadata > ; 
1313
1414  beforeEach ( ( )  =>  { 
1515    mockMetadata  =  { 
@@ -19,7 +19,7 @@ describe('renderChartConfig', () => {
1919      ] ) , 
2020      getMaterializedColumnsLookupTable : jest . fn ( ) . mockResolvedValue ( null ) , 
2121      getColumn : jest . fn ( ) . mockResolvedValue ( {  type : 'DateTime'  } ) , 
22-     }  as  unknown  as  Metadata ; 
22+     }  as  unknown  as  jest . Mocked < Metadata > ; 
2323  } ) ; 
2424
2525  const  gaugeConfiguration : ChartConfigWithOptDateRange  =  { 
@@ -630,4 +630,168 @@ describe('renderChartConfig', () => {
630630      expect ( actual ) . toMatchSnapshot ( ) ; 
631631    } ) ; 
632632  } ) ; 
633+ 
634+   describe ( 'timeFilterExpr' ,  ( )  =>  { 
635+     type  TimeFilterExprTestCase  =  { 
636+       timestampValueExpression : string ; 
637+       dateRangeStartInclusive ?: boolean ; 
638+       dateRangeEndInclusive ?: boolean ; 
639+       dateRange : [ Date ,  Date ] ; 
640+       includedDataInterval ?: string ; 
641+       expected : string ; 
642+       description : string ; 
643+     } ; 
644+ 
645+     const  testCases : TimeFilterExprTestCase [ ]  =  [ 
646+       { 
647+         description : 'with basic timestampValueExpression' , 
648+         timestampValueExpression : 'timestamp' , 
649+         dateRange : [ 
650+           new  Date ( '2025-02-12 00:12:34Z' ) , 
651+           new  Date ( '2025-02-14 00:12:34Z' ) , 
652+         ] , 
653+         expected : `(timestamp >= fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
654+       } , 
655+       { 
656+         description : 'with dateRangeEndInclusive=false' , 
657+         timestampValueExpression : 'timestamp' , 
658+         dateRange : [ 
659+           new  Date ( '2025-02-12 00:12:34Z' ) , 
660+           new  Date ( '2025-02-14 00:12:34Z' ) , 
661+         ] , 
662+         dateRangeEndInclusive : false , 
663+         expected : `(timestamp >= fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
664+       } , 
665+       { 
666+         description : 'with dateRangeStartInclusive=false' , 
667+         timestampValueExpression : 'timestamp' , 
668+         dateRange : [ 
669+           new  Date ( '2025-02-12 00:12:34Z' ) , 
670+           new  Date ( '2025-02-14 00:12:34Z' ) , 
671+         ] , 
672+         dateRangeStartInclusive : false , 
673+         expected : `(timestamp > fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
674+       } , 
675+       { 
676+         description : 'with includedDataInterval' , 
677+         timestampValueExpression : 'timestamp' , 
678+         dateRange : [ 
679+           new  Date ( '2025-02-12 00:12:34Z' ) , 
680+           new  Date ( '2025-02-14 00:12:34Z' ) , 
681+         ] , 
682+         includedDataInterval : '1 WEEK' , 
683+         expected : `(timestamp >= toStartOfInterval(fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
684+       } , 
685+       { 
686+         description : 'with date type timestampValueExpression' , 
687+         timestampValueExpression : 'date' , 
688+         dateRange : [ 
689+           new  Date ( '2025-02-12 00:12:34Z' ) , 
690+           new  Date ( '2025-02-14 00:12:34Z' ) , 
691+         ] , 
692+         expected : `(date >= toDate(fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
693+       } , 
694+       { 
695+         description : 'with multiple timestampValueExpression parts' , 
696+         timestampValueExpression : 'timestamp, date' , 
697+         dateRange : [ 
698+           new  Date ( '2025-02-12 00:12:34Z' ) , 
699+           new  Date ( '2025-02-14 00:12:34Z' ) , 
700+         ] , 
701+         expected : `(timestamp >= fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
702+       } , 
703+       { 
704+         description : 'with toStartOfDay() in timestampExpr' , 
705+         timestampValueExpression : 'toStartOfDay(timestamp)' , 
706+         dateRange : [ 
707+           new  Date ( '2025-02-12 00:12:34Z' ) , 
708+           new  Date ( '2025-02-14 00:12:34Z' ) , 
709+         ] , 
710+         expected : `(toStartOfDay(timestamp) >= toStartOfDay(fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
711+       } , 
712+       { 
713+         description : 'with toStartOfDay  () in timestampExpr' , 
714+         timestampValueExpression : 'toStartOfDay  (timestamp)' , 
715+         dateRange : [ 
716+           new  Date ( '2025-02-12 00:12:34Z' ) , 
717+           new  Date ( '2025-02-14 00:12:34Z' ) , 
718+         ] , 
719+         expected : `(toStartOfDay  (timestamp) >= toStartOfDay(fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
720+       } , 
721+       { 
722+         description : 'with toStartOfInterval() in timestampExpr' , 
723+         timestampValueExpression :
724+           'toStartOfInterval(timestamp, INTERVAL 12  MINUTE)' , 
725+         dateRange : [ 
726+           new  Date ( '2025-02-12 00:12:34Z' ) , 
727+           new  Date ( '2025-02-14 00:12:34Z' ) , 
728+         ] , 
729+         expected : `(toStartOfInterval(timestamp, INTERVAL 12  MINUTE) >= toStartOfInterval(fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
730+       } , 
731+       { 
732+         description :
733+           'with toStartOfInterval() with lowercase interval in timestampExpr' , 
734+         timestampValueExpression :
735+           'toStartOfInterval(timestamp, interval 1 minute)' , 
736+         dateRange : [ 
737+           new  Date ( '2025-02-12 00:12:34Z' ) , 
738+           new  Date ( '2025-02-14 00:12:34Z' ) , 
739+         ] , 
740+         expected : `(toStartOfInterval(timestamp, interval 1 minute) >= toStartOfInterval(fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
741+       } , 
742+       { 
743+         description : 'with toStartOfInterval() with timezone and offset' , 
744+         timestampValueExpression : `toStartOfInterval(timestamp, INTERVAL 1 MINUTE, toDateTime('2023-01-01 14:35:30'), 'America/New_York')` , 
745+         dateRange : [ 
746+           new  Date ( '2025-02-12 00:12:34Z' ) , 
747+           new  Date ( '2025-02-14 00:12:34Z' ) , 
748+         ] , 
749+         expected : `(toStartOfInterval(timestamp, INTERVAL 1 MINUTE, toDateTime('2023-01-01 14:35:30'), 'America/New_York') >= toStartOfInterval(fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
750+       } , 
751+       { 
752+         description : 'with nonstandard spacing' , 
753+         timestampValueExpression : ` toStartOfInterval ( timestamp ,  INTERVAL  1 MINUTE , toDateTime ( '2023-01-01 14:35:30' ),  'America/New_York' ) ` , 
754+         dateRange : [ 
755+           new  Date ( '2025-02-12 00:12:34Z' ) , 
756+           new  Date ( '2025-02-14 00:12:34Z' ) , 
757+         ] , 
758+         expected : `(toStartOfInterval ( timestamp ,  INTERVAL  1 MINUTE , toDateTime ( '2023-01-01 14:35:30' ),  'America/New_York' ) >= toStartOfInterval(fromUnixTimestamp64Milli(${ new  Date ( '2025-02-12 00:12:34Z' ) . getTime ( ) } ${ new  Date ( '2025-02-14 00:12:34Z' ) . getTime ( ) }  , 
759+       } , 
760+     ] ; 
761+ 
762+     beforeEach ( ( )  =>  { 
763+       mockMetadata . getColumn . mockImplementation ( async  ( {  column } )  => 
764+         column  ===  'date' 
765+           ? ( {  type : 'Date'  }  as  ColumnMeta ) 
766+           : ( {  type : 'DateTime'  }  as  ColumnMeta ) , 
767+       ) ; 
768+     } ) ; 
769+ 
770+     it . each ( testCases ) ( 
771+       'should generate a time filter expression $description' , 
772+       async  ( { 
773+         timestampValueExpression, 
774+         dateRangeEndInclusive =  true , 
775+         dateRangeStartInclusive =  true , 
776+         dateRange, 
777+         expected, 
778+         includedDataInterval, 
779+       } )  =>  { 
780+         const  actual  =  await  timeFilterExpr ( { 
781+           timestampValueExpression, 
782+           dateRangeEndInclusive, 
783+           dateRangeStartInclusive, 
784+           dateRange, 
785+           connectionId : 'test-connection' , 
786+           databaseName : 'default' , 
787+           metadata : mockMetadata , 
788+           tableName : '' , 
789+           includedDataInterval, 
790+         } ) ; 
791+ 
792+         const  actualSql  =  parameterizedQueryToSql ( actual ) ; 
793+         expect ( actualSql ) . toBe ( expected ) ; 
794+       } , 
795+     ) ; 
796+   } ) ; 
633797} ) ; 
0 commit comments