MySQL: Add parseTime=true to SQL connections (#92469)

This commit is contained in:
Ryan McKinley 2024-08-27 14:16:04 +03:00 committed by GitHub
parent c98e3e0483
commit c59dddf7af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 47 additions and 3 deletions

View File

@ -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 |
| `showDashboardValidationWarnings` | Show warnings when dashboards do not validate against the schema |
| `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 |
| `editPanelCSVDragAndDrop` | Enables drag and drop for CSV and Excel files |
| `lokiQuerySplittingConfig` | Give users the option to configure split durations for Loki queries |

View File

@ -45,6 +45,7 @@ export interface FeatureToggles {
cloudWatchCrossAccountQuerying?: boolean;
showDashboardValidationWarnings?: boolean;
mysqlAnsiQuotes?: boolean;
mysqlParseTime?: boolean;
accessControlOnCall?: boolean;
nestedFolders?: boolean;
alertingBacktesting?: boolean;

View File

@ -214,6 +214,12 @@ var (
Stage: FeatureStageExperimental,
Owner: grafanaSearchAndStorageSquad,
},
{
Name: "mysqlParseTime",
Description: "Ensure the parseTime flag is set for MySQL driver",
Stage: FeatureStageExperimental,
Owner: grafanaSearchAndStorageSquad,
},
{
Name: "accessControlOnCall",
Description: "Access control primitives for OnCall",

View File

@ -26,6 +26,7 @@ grpcServer,preview,@grafana/search-and-storage,false,false,false
cloudWatchCrossAccountQuerying,GA,@grafana/aws-datasources,false,false,false
showDashboardValidationWarnings,experimental,@grafana/dashboards-squad,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
nestedFolders,GA,@grafana/search-and-storage,false,false,false
alertingBacktesting,experimental,@grafana/alerting-squad,false,false,false

1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
26 cloudWatchCrossAccountQuerying GA @grafana/aws-datasources false false false
27 showDashboardValidationWarnings experimental @grafana/dashboards-squad false false false
28 mysqlAnsiQuotes experimental @grafana/search-and-storage false false false
29 mysqlParseTime experimental @grafana/search-and-storage false false false
30 accessControlOnCall preview @grafana/identity-access-team false false false
31 nestedFolders GA @grafana/search-and-storage false false false
32 alertingBacktesting experimental @grafana/alerting-squad false false false

View File

@ -115,6 +115,10 @@ const (
// Use double quotes to escape keyword in a MySQL query
FlagMysqlAnsiQuotes = "mysqlAnsiQuotes"
// FlagMysqlParseTime
// Ensure the parseTime flag is set for MySQL driver
FlagMysqlParseTime = "mysqlParseTime"
// FlagAccessControlOnCall
// Access control primitives for OnCall
FlagAccessControlOnCall = "accessControlOnCall"

View File

@ -1789,6 +1789,18 @@
"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": {
"name": "nestedFolders",

View File

@ -791,7 +791,11 @@ func TestIntegrationSoftDeletion(t *testing.T) {
// Set up dashboard store.
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)
require.NoError(t, err)

View File

@ -166,6 +166,10 @@ func (dbCfg *DatabaseConfig) buildConnectionString(cfg *setting.Cfg, features fe
cnnstr += fmt.Sprintf("&transaction_isolation=%s", val)
}
if features != nil && features.IsEnabledGlobally(featuremgmt.FlagMysqlParseTime) {
cnnstr += "&parseTime=true"
}
if features != nil && features.IsEnabledGlobally(featuremgmt.FlagMysqlAnsiQuotes) {
cnnstr += "&sql_mode='ANSI_QUOTES'"
}

View File

@ -296,15 +296,24 @@ func (ss *SQLStore) initEngine(engine *xorm.Engine) error {
}
}
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
engine, err = xorm.NewEngine(ss.dbCfg.Type, ss.dbCfg.ConnectionString)
engine, err = xorm.NewEngine(ss.dbCfg.Type, connection)
if err != nil {
return err
}
// 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 ss.dbCfg.Type == migrator.MySQL {
engine, err = ss.ensureTransactionIsolationCompatibility(engine, ss.dbCfg.ConnectionString)
engine, err = ss.ensureTransactionIsolationCompatibility(engine, connection)
if err != nil {
return err
}
@ -481,6 +490,7 @@ func getCfgForTesting(opts ...InitTestDBOpt) *setting.Cfg {
func getFeaturesForTesting(opts ...InitTestDBOpt) featuremgmt.FeatureToggles {
featureKeys := []any{
featuremgmt.FlagPanelTitleSearch,
featuremgmt.FlagMysqlParseTime,
}
for _, opt := range opts {
if len(opt.FeatureFlags) > 0 {

View File

@ -31,6 +31,7 @@ func getEngineMySQL(getter *sectionGetter, tracer tracing.Tracer) (*xorm.Engine,
config.Loc = time.UTC
config.AllowNativePasswords = true
config.ClientFoundRows = true
config.ParseTime = true
// allow executing multiple SQL statements in a single roundtrip, and also
// enable executing the CALL statement to run stored procedures that execute