Skip to content

Commit

Permalink
[SQL] Address review comments discussed async
Browse files Browse the repository at this point in the history
  • Loading branch information
shmsr committed Jul 10, 2023
1 parent 7fa3ff0 commit 3275971
Showing 1 changed file with 37 additions and 11 deletions.
48 changes: 37 additions & 11 deletions x-pack/metricbeat/module/sql/query/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,26 +106,37 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
return b, nil
}

// queryDBNames returns the command to list databases present in a server
// queryDBNames returns the query to list databases present in a server
// as per the driver name. If the given driver is not supported, queryDBNames
// returns an empty query.
func queryDBNames(driver string) string {
switch sql.SwitchDriverName(driver) {
case "mysql":
return "SHOW DATABASES"
case "mssql":
return "SELECT [name] FROM sys.databases WITH (NOLOCK) WHERE state = 0 AND HAS_DBACCESS([name]) = 1"
case "godror":
// NOTE: Requires necessary priviledges to access DBA_USERS
// Ref: https://stackoverflow.com/a/3005623/5821408
return "SELECT * FROM DBA_USERS"
case "postgres":
return "SELECT datname FROM pg_database"
// case "mysql":
// return "SHOW DATABASES"
// case "godror":
// // NOTE: Requires necessary priviledges to access DBA_USERS
// // Ref: https://stackoverflow.com/a/3005623/5821408
// return "SELECT * FROM DBA_USERS"
// case "postgres":
// return "SELECT datname FROM pg_database"
}

return ""
}

// dbSelector returns the statement to select a named database to run the
// subsequent statements. If the given driver is not supported, dbSelector
// returns an empty query.
func dbSelector(driver, dbName string) string {
switch sql.SwitchDriverName(driver) {
case "mssql":
return fmt.Sprintf("USE [%s];", dbName)
}
return ""
}

func (m *MetricSet) fetch(ctx context.Context, db *sql.DbClient, reporter mb.ReporterV2, queries []query) error {
merged := make(mapstr.M, 0)

Expand Down Expand Up @@ -211,6 +222,19 @@ func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error {
return nil
}

// NOTE: Only mssql driver is supported for now because:
//
// * Difference in queries to fetch the name of the databases
// * The statement to select a named database (for subsequent statements
// to be executed) may not be generic i.e, USE statement (e.g., USE <db_name>)
// works for MSSQL but not Oracle.
//
// TODO: Add the feature for other drivers when need arises.
validQuery := queryDBNames(m.Config.Driver)
if validQuery == "" {
return fmt.Errorf("fetch from all databases feature is not supported for driver: %s", m.Config.Driver)
}

// Discover all databases in the server and execute given queries on each
// of the databases.
dbNames, err := db.FetchTableMode(ctx, queryDBNames(m.Config.Driver))
Expand Down Expand Up @@ -241,9 +265,11 @@ func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error {
continue
}

// Prefix `USE <db_name>;` to the query
// Prefix dbSelector to the query based on the driver
// provided.
// Example: USE <dbName>; @command (or @query)
for i := range qs {
qs[i].Query = fmt.Sprintf("USE [%s]; ", dbName) + qs[i].Query
qs[i].Query = dbSelector(m.Config.Driver, dbName) + " " + qs[i].Query
}

err = m.fetch(ctx, db, reporter, qs)
Expand Down

0 comments on commit 3275971

Please sign in to comment.