2017-04-19 16:09:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  mysql  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"regexp" 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-27 17:26:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 16:09:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-05-30 15:58:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/components/gtime" 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 16:09:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/tsdb" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  rsIdentifier  =  ` ([_a-zA-Z0-9]+) `  
						 
					
						
							
								
									
										
										
										
											2017-04-20 17:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  sExpr  =  ` \$ `  +  rsIdentifier  +  ` \(([^\)]*)\) `  
						 
					
						
							
								
									
										
										
										
											2017-04-19 16:09:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type  mySqlMacroEngine  struct  {  
						 
					
						
							
								
									
										
										
										
											2018-09-13 22:51:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* tsdb . SqlMacroEngineBase 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									timeRange  * tsdb . TimeRange 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									query      * tsdb . Query 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 16:09:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  newMysqlMacroEngine ( )  tsdb . SqlMacroEngine  {  
						 
					
						
							
								
									
										
										
										
											2018-09-13 22:51:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  & mySqlMacroEngine { SqlMacroEngineBase :  tsdb . NewSqlMacroEngineBase ( ) } 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 16:09:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( m  * mySqlMacroEngine )  Interpolate ( query  * tsdb . Query ,  timeRange  * tsdb . TimeRange ,  sql  string )  ( string ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . timeRange  =  timeRange 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . query  =  query 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 16:09:52 +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-03 02:24:15 +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-04-19 23:26:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  &&  macroError  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 16:09:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											macroError  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "macro_error()" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  res 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  macroError  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  macroError 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  sql ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( m  * mySqlMacroEngine )  evaluateMacro ( name  string ,  args  [ ] string )  ( string ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2017-04-19 16:09:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									switch  name  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-22 22:40:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "__timeEpoch" ,  "__time" : 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 16:09:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  len ( args )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "missing time column argument for macro %v" ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 23:26:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "UNIX_TIMESTAMP(%s) as time_sec" ,  args [ 0 ] ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									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-10-25 16:29:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%s BETWEEN FROM_UNIXTIME(%d) AND FROM_UNIXTIME(%d)" ,  args [ 0 ] ,  m . timeRange . GetFromAsSecondsEpoch ( ) ,  m . timeRange . GetToAsSecondsEpoch ( ) ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-30 21:18:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "__timeFrom" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "FROM_UNIXTIME(%d)" ,  m . timeRange . GetFromAsSecondsEpoch ( ) ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  "__timeTo" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "FROM_UNIXTIME(%d)" ,  m . timeRange . GetToAsSecondsEpoch ( ) ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-27 17:26:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "__timeGroup" : 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 02:50:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  len ( args )  <  2  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-27 17:26:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											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 ] ,  ` '" ` ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-27 17:26:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "error parsing interval %v" ,  args [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 02:50:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  len ( args )  ==  3  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-12 16:51:58 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  :=  tsdb . SetupFillmode ( m . query ,  interval ,  args [ 2 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  "" ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 02:50:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-01 21:59:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "UNIX_TIMESTAMP(%s) DIV %.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  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  tg  +  " AS \"time\"" ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-09 05:36:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "__unixEpochFilter" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "missing time column argument for macro %v" ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-27 00:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%s >= %d AND %s <= %d" ,  args [ 0 ] ,  m . timeRange . GetFromAsSecondsEpoch ( ) ,  args [ 0 ] ,  m . timeRange . GetToAsSecondsEpoch ( ) ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 05:29:57 +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" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%d" ,  m . timeRange . GetFromAsTimeUTC ( ) . UnixNano ( ) ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  "__unixEpochNanoTo" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%d" ,  m . timeRange . GetToAsTimeUTC ( ) . UnixNano ( ) ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 18:17:05 +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:17:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  fmt . Errorf ( "error parsing interval %v" ,  args [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( args )  ==  3  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											err  :=  tsdb . SetupFillmode ( m . query ,  interval ,  args [ 2 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  "" ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "%s DIV %v * %v" ,  args [ 0 ] ,  interval . Seconds ( ) ,  interval . Seconds ( ) ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  "__unixEpochGroupAlias" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tg ,  err  :=  m . evaluateMacro ( "__unixEpochGroup" ,  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  tg  +  " AS \"time\"" ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 16:09:52 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  fmt . Errorf ( "Unknown macro %v" ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}