2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  mssql  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"regexp" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-14 05:49:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-05-30 15:58:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/components/gtime" 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-19 20:32:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/tsdb" 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-11 03:50:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/tsdb/sqleng" 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  rsIdentifier  =  ` ([_a-zA-Z0-9]+) `  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  sExpr  =  ` \$ `  +  rsIdentifier  +  ` \(([^\)]*)\) `  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:11:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type  msSqlMacroEngine  struct  {  
						 
					
						
							
								
									
										
										
										
											2019-09-11 03:50:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* sqleng . SqlMacroEngineBase 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:11:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									timeRange  * tsdb . TimeRange 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									query      * tsdb . Query 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-09-11 03:50:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  newMssqlMacroEngine ( )  sqleng . SqlMacroEngine  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  & msSqlMacroEngine { SqlMacroEngineBase :  sqleng . NewSqlMacroEngineBase ( ) } 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:11:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( m  * msSqlMacroEngine )  Interpolate ( query  * tsdb . Query ,  timeRange  * tsdb . TimeRange ,  sql  string )  ( string ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . timeRange  =  timeRange 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . query  =  query 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									rExp ,  _  :=  regexp . Compile ( sExpr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  macroError  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-13 22:51:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									sql  =  m . ReplaceAllStringSubmatchFunc ( rExp ,  sql ,  func ( groups  [ ] string )  string  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 23:03:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										args  :=  strings . Split ( groups [ 2 ] ,  "," ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  i ,  arg  :=  range  args  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											args [ i ]  =  strings . Trim ( arg ,  " " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res ,  err  :=  m . evaluateMacro ( groups [ 1 ] ,  args ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  &&  macroError  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											macroError  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "macro_error()" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  res 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  macroError  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  macroError 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  sql ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:11:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( m  * msSqlMacroEngine )  evaluateMacro ( name  string ,  args  [ ] string )  ( string ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									switch  name  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  "__time" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "missing time column argument for macro %v" ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-13 04:43:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%s AS time" ,  args [ 0 ] ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  "__timeEpoch" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "missing time column argument for macro %v" ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-22 21:55:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "DATEDIFF(second, '1970-01-01', %s) AS time" ,  args [ 0 ] ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  "__timeFilter" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "missing time column argument for macro %v" ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-06-26 04:11:58 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:11:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%s BETWEEN '%s' AND '%s'" ,  args [ 0 ] ,  m . timeRange . GetFromAsTimeUTC ( ) . Format ( time . RFC3339 ) ,  m . timeRange . GetToAsTimeUTC ( ) . Format ( time . RFC3339 ) ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-30 21:18:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "__timeFrom" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "'%s'" ,  m . timeRange . GetFromAsTimeUTC ( ) . Format ( time . RFC3339 ) ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  "__timeTo" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "'%s'" ,  m . timeRange . GetToAsTimeUTC ( ) . Format ( time . RFC3339 ) ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-14 05:49:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "__timeGroup" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  <  2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "macro %v needs time column and interval" ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-30 15:58:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										interval ,  err  :=  gtime . ParseInterval ( strings . Trim ( args [ 1 ] ,  ` '" ` ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-14 05:49:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "error parsing interval %v" ,  args [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 20:11:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  len ( args )  ==  3  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-11 03:50:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  :=  sqleng . SetupFillmode ( m . query ,  interval ,  args [ 2 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-12 16:51:58 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  "" ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 20:11:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-01 21:57:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "FLOOR(DATEDIFF(second, '1970-01-01', %s)/%.0f)*%.0f" ,  args [ 0 ] ,  interval . Seconds ( ) ,  interval . Seconds ( ) ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 02:58:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "__timeGroupAlias" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tg ,  err  :=  m . evaluateMacro ( "__timeGroup" ,  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-17 18:27:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  tg  +  " AS [time]" ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-02 02:58:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  "__unixEpochFilter" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "missing time column argument for macro %v" ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:11:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%s >= %d AND %s <= %d" ,  args [ 0 ] ,  m . timeRange . GetFromAsSecondsEpoch ( ) ,  args [ 0 ] ,  m . timeRange . GetToAsSecondsEpoch ( ) ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 04:43:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "__unixEpochNanoFilter" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "missing time column argument for macro %v" ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%s >= %d AND %s <= %d" ,  args [ 0 ] ,  m . timeRange . GetFromAsTimeUTC ( ) . UnixNano ( ) ,  args [ 0 ] ,  m . timeRange . GetToAsTimeUTC ( ) . UnixNano ( ) ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  "__unixEpochNanoFrom" : 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 05:25:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%d" ,  m . timeRange . GetFromAsTimeUTC ( ) . UnixNano ( ) ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 04:43:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "__unixEpochNanoTo" : 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 05:25:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%d" ,  m . timeRange . GetToAsTimeUTC ( ) . UnixNano ( ) ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 18:23:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "__unixEpochGroup" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  <  2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "macro %v needs time column and interval and optional fill value" ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-30 15:58:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										interval ,  err  :=  gtime . ParseInterval ( strings . Trim ( args [ 1 ] ,  ` ' ` ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 18:23:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "error parsing interval %v" ,  args [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  ==  3  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-11 03:50:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  :=  sqleng . SetupFillmode ( m . query ,  interval ,  args [ 2 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 18:23:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  "" ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "FLOOR(%s/%v)*%v" ,  args [ 0 ] ,  interval . Seconds ( ) ,  interval . Seconds ( ) ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  "__unixEpochGroupAlias" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tg ,  err  :=  m . evaluateMacro ( "__unixEpochGroup" ,  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-17 18:27:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  tg  +  " AS [time]" ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 18:23:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-05 18:29:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  "" ,  fmt . Errorf ( "unknown macro %q" ,  name ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 19:40:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}