fix(tools/mysqlsql): Handle nil panic and connection leak in invoke (#758)

Copy fix from #757. 

The Invoke function had two bugs:

A panic would occur when scanning a row containing a NULL value in a
TEXT or VARCHAR column. The code did not check for nil before attempting
a type assertion on the scanned value.

The *sql.Rows result was not being closed on all code paths, leading to
connection leaks that could exhaust the database connection pool.

This change corrects both issues. A guard clause now checks for nil
values before processing, and rows.Close() is deferred to guarantee the
connection is released.
This commit is contained in:
Yuan
2025-06-26 13:54:59 -07:00
committed by GitHub
parent 7badba42ee
commit cbb4a33351

View File

@@ -153,6 +153,7 @@ func (t Tool) Invoke(ctx context.Context, params tools.ParamValues) ([]any, erro
for i := range rawValues {
values[i] = &rawValues[i]
}
defer results.Close()
colTypes, err := results.ColumnTypes()
if err != nil {
@@ -167,29 +168,26 @@ func (t Tool) Invoke(ctx context.Context, params tools.ParamValues) ([]any, erro
}
vMap := make(map[string]any)
for i, name := range cols {
val := rawValues[i]
if val == nil {
vMap[name] = nil
continue
}
// mysql driver return []uint8 type for "TEXT", "VARCHAR", and "NVARCHAR"
// we'll need to cast it back to string
switch colTypes[i].DatabaseTypeName() {
case "TEXT", "VARCHAR", "NVARCHAR":
if rawValues[i] != nil {
vMap[name] = string(rawValues[i].([]byte))
} else {
vMap[name] = nil
}
vMap[name] = string(val.([]byte))
default:
vMap[name] = rawValues[i]
vMap[name] = val
}
}
out = append(out, vMap)
}
err = results.Close()
if err != nil {
return nil, fmt.Errorf("unable to close rows: %w", err)
}
if err := results.Err(); err != nil {
return nil, fmt.Errorf("errors encountered by results.Scan: %w", err)
return nil, fmt.Errorf("errors encountered during row iteration: %w", err)
}
return out, nil