mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
MySQL: Add parseTime=true to SQL connections (#92469)
This commit is contained in:
parent
c98e3e0483
commit
c59dddf7af
@ -122,6 +122,7 @@ Experimental features might be changed or removed without prior notice.
|
|||||||
| `logRequestsInstrumentedAsUnknown` | Logs the path for requests that are instrumented as unknown |
|
| `logRequestsInstrumentedAsUnknown` | Logs the path for requests that are instrumented as unknown |
|
||||||
| `showDashboardValidationWarnings` | Show warnings when dashboards do not validate against the schema |
|
| `showDashboardValidationWarnings` | Show warnings when dashboards do not validate against the schema |
|
||||||
| `mysqlAnsiQuotes` | Use double quotes to escape keyword in a MySQL query |
|
| `mysqlAnsiQuotes` | Use double quotes to escape keyword in a MySQL query |
|
||||||
|
| `mysqlParseTime` | Ensure the parseTime flag is set for MySQL driver |
|
||||||
| `alertingBacktesting` | Rule backtesting API for alerting |
|
| `alertingBacktesting` | Rule backtesting API for alerting |
|
||||||
| `editPanelCSVDragAndDrop` | Enables drag and drop for CSV and Excel files |
|
| `editPanelCSVDragAndDrop` | Enables drag and drop for CSV and Excel files |
|
||||||
| `lokiQuerySplittingConfig` | Give users the option to configure split durations for Loki queries |
|
| `lokiQuerySplittingConfig` | Give users the option to configure split durations for Loki queries |
|
||||||
|
@ -45,6 +45,7 @@ export interface FeatureToggles {
|
|||||||
cloudWatchCrossAccountQuerying?: boolean;
|
cloudWatchCrossAccountQuerying?: boolean;
|
||||||
showDashboardValidationWarnings?: boolean;
|
showDashboardValidationWarnings?: boolean;
|
||||||
mysqlAnsiQuotes?: boolean;
|
mysqlAnsiQuotes?: boolean;
|
||||||
|
mysqlParseTime?: boolean;
|
||||||
accessControlOnCall?: boolean;
|
accessControlOnCall?: boolean;
|
||||||
nestedFolders?: boolean;
|
nestedFolders?: boolean;
|
||||||
alertingBacktesting?: boolean;
|
alertingBacktesting?: boolean;
|
||||||
|
@ -214,6 +214,12 @@ var (
|
|||||||
Stage: FeatureStageExperimental,
|
Stage: FeatureStageExperimental,
|
||||||
Owner: grafanaSearchAndStorageSquad,
|
Owner: grafanaSearchAndStorageSquad,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "mysqlParseTime",
|
||||||
|
Description: "Ensure the parseTime flag is set for MySQL driver",
|
||||||
|
Stage: FeatureStageExperimental,
|
||||||
|
Owner: grafanaSearchAndStorageSquad,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "accessControlOnCall",
|
Name: "accessControlOnCall",
|
||||||
Description: "Access control primitives for OnCall",
|
Description: "Access control primitives for OnCall",
|
||||||
|
@ -26,6 +26,7 @@ grpcServer,preview,@grafana/search-and-storage,false,false,false
|
|||||||
cloudWatchCrossAccountQuerying,GA,@grafana/aws-datasources,false,false,false
|
cloudWatchCrossAccountQuerying,GA,@grafana/aws-datasources,false,false,false
|
||||||
showDashboardValidationWarnings,experimental,@grafana/dashboards-squad,false,false,false
|
showDashboardValidationWarnings,experimental,@grafana/dashboards-squad,false,false,false
|
||||||
mysqlAnsiQuotes,experimental,@grafana/search-and-storage,false,false,false
|
mysqlAnsiQuotes,experimental,@grafana/search-and-storage,false,false,false
|
||||||
|
mysqlParseTime,experimental,@grafana/search-and-storage,false,false,false
|
||||||
accessControlOnCall,preview,@grafana/identity-access-team,false,false,false
|
accessControlOnCall,preview,@grafana/identity-access-team,false,false,false
|
||||||
nestedFolders,GA,@grafana/search-and-storage,false,false,false
|
nestedFolders,GA,@grafana/search-and-storage,false,false,false
|
||||||
alertingBacktesting,experimental,@grafana/alerting-squad,false,false,false
|
alertingBacktesting,experimental,@grafana/alerting-squad,false,false,false
|
||||||
|
|
@ -115,6 +115,10 @@ const (
|
|||||||
// Use double quotes to escape keyword in a MySQL query
|
// Use double quotes to escape keyword in a MySQL query
|
||||||
FlagMysqlAnsiQuotes = "mysqlAnsiQuotes"
|
FlagMysqlAnsiQuotes = "mysqlAnsiQuotes"
|
||||||
|
|
||||||
|
// FlagMysqlParseTime
|
||||||
|
// Ensure the parseTime flag is set for MySQL driver
|
||||||
|
FlagMysqlParseTime = "mysqlParseTime"
|
||||||
|
|
||||||
// FlagAccessControlOnCall
|
// FlagAccessControlOnCall
|
||||||
// Access control primitives for OnCall
|
// Access control primitives for OnCall
|
||||||
FlagAccessControlOnCall = "accessControlOnCall"
|
FlagAccessControlOnCall = "accessControlOnCall"
|
||||||
|
@ -1789,6 +1789,18 @@
|
|||||||
"codeowner": "@grafana/search-and-storage"
|
"codeowner": "@grafana/search-and-storage"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"name": "mysqlParseTime",
|
||||||
|
"resourceVersion": "1724750152191",
|
||||||
|
"creationTimestamp": "2024-08-27T09:15:52Z"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"description": "Ensure the parseTime flag is set for MySQL driver",
|
||||||
|
"stage": "experimental",
|
||||||
|
"codeowner": "@grafana/search-and-storage"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"name": "nestedFolders",
|
"name": "nestedFolders",
|
||||||
|
@ -791,7 +791,11 @@ func TestIntegrationSoftDeletion(t *testing.T) {
|
|||||||
|
|
||||||
// Set up dashboard store.
|
// Set up dashboard store.
|
||||||
quotaService := quotatest.New(false, nil)
|
quotaService := quotatest.New(false, nil)
|
||||||
featureToggles := featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch, featuremgmt.FlagDashboardRestore)
|
featureToggles := featuremgmt.WithFeatures(
|
||||||
|
featuremgmt.FlagPanelTitleSearch,
|
||||||
|
featuremgmt.FlagDashboardRestore,
|
||||||
|
featuremgmt.FlagMysqlParseTime,
|
||||||
|
)
|
||||||
dashboardStore, err := database.ProvideDashboardStore(replStore, cfg, featureToggles, tagimpl.ProvideService(sqlStore), quotaService)
|
dashboardStore, err := database.ProvideDashboardStore(replStore, cfg, featureToggles, tagimpl.ProvideService(sqlStore), quotaService)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -166,6 +166,10 @@ func (dbCfg *DatabaseConfig) buildConnectionString(cfg *setting.Cfg, features fe
|
|||||||
cnnstr += fmt.Sprintf("&transaction_isolation=%s", val)
|
cnnstr += fmt.Sprintf("&transaction_isolation=%s", val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if features != nil && features.IsEnabledGlobally(featuremgmt.FlagMysqlParseTime) {
|
||||||
|
cnnstr += "&parseTime=true"
|
||||||
|
}
|
||||||
|
|
||||||
if features != nil && features.IsEnabledGlobally(featuremgmt.FlagMysqlAnsiQuotes) {
|
if features != nil && features.IsEnabledGlobally(featuremgmt.FlagMysqlAnsiQuotes) {
|
||||||
cnnstr += "&sql_mode='ANSI_QUOTES'"
|
cnnstr += "&sql_mode='ANSI_QUOTES'"
|
||||||
}
|
}
|
||||||
|
@ -296,15 +296,24 @@ func (ss *SQLStore) initEngine(engine *xorm.Engine) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if engine == nil {
|
if engine == nil {
|
||||||
|
connection := ss.dbCfg.ConnectionString
|
||||||
|
|
||||||
|
// Ensure that parseTime is enabled for MySQL
|
||||||
|
if ss.dbCfg.Type == migrator.MySQL && !strings.Contains(connection, "parseTime=") {
|
||||||
|
if ss.features.IsEnabledGlobally(featuremgmt.FlagMysqlParseTime) {
|
||||||
|
connection += "&parseTime=true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
engine, err = xorm.NewEngine(ss.dbCfg.Type, ss.dbCfg.ConnectionString)
|
engine, err = xorm.NewEngine(ss.dbCfg.Type, connection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Only for MySQL or MariaDB, verify we can connect with the current connection string's system var for transaction isolation.
|
// Only for MySQL or MariaDB, verify we can connect with the current connection string's system var for transaction isolation.
|
||||||
// If not, create a new engine with a compatible connection string.
|
// If not, create a new engine with a compatible connection string.
|
||||||
if ss.dbCfg.Type == migrator.MySQL {
|
if ss.dbCfg.Type == migrator.MySQL {
|
||||||
engine, err = ss.ensureTransactionIsolationCompatibility(engine, ss.dbCfg.ConnectionString)
|
engine, err = ss.ensureTransactionIsolationCompatibility(engine, connection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -481,6 +490,7 @@ func getCfgForTesting(opts ...InitTestDBOpt) *setting.Cfg {
|
|||||||
func getFeaturesForTesting(opts ...InitTestDBOpt) featuremgmt.FeatureToggles {
|
func getFeaturesForTesting(opts ...InitTestDBOpt) featuremgmt.FeatureToggles {
|
||||||
featureKeys := []any{
|
featureKeys := []any{
|
||||||
featuremgmt.FlagPanelTitleSearch,
|
featuremgmt.FlagPanelTitleSearch,
|
||||||
|
featuremgmt.FlagMysqlParseTime,
|
||||||
}
|
}
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
if len(opt.FeatureFlags) > 0 {
|
if len(opt.FeatureFlags) > 0 {
|
||||||
|
@ -31,6 +31,7 @@ func getEngineMySQL(getter *sectionGetter, tracer tracing.Tracer) (*xorm.Engine,
|
|||||||
config.Loc = time.UTC
|
config.Loc = time.UTC
|
||||||
config.AllowNativePasswords = true
|
config.AllowNativePasswords = true
|
||||||
config.ClientFoundRows = true
|
config.ClientFoundRows = true
|
||||||
|
config.ParseTime = true
|
||||||
|
|
||||||
// allow executing multiple SQL statements in a single roundtrip, and also
|
// allow executing multiple SQL statements in a single roundtrip, and also
|
||||||
// enable executing the CALL statement to run stored procedures that execute
|
// enable executing the CALL statement to run stored procedures that execute
|
||||||
|
Loading…
Reference in New Issue
Block a user