fix(storage): close rows before nested queries to prevent PostgreSQL driver error (#1503)
Fixes #1435
This commit is contained in:
parent
42b51f5da5
commit
bc433161d6
@ -1176,23 +1176,26 @@ func (s *Store) GetAllSuiteStatuses(params *paging.SuiteStatusParams) ([]*suite.
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
|
// Collect all suite statuses first before making nested queries.
|
||||||
|
// The lib/pq driver requires the previous query to be fully closed before starting
|
||||||
|
// new queries in the same transaction, otherwise it returns "pq: unexpected Parse
|
||||||
|
// response 'C'" errors. See: https://github.com/TwiN/gatus/issues/1435
|
||||||
var suiteStatuses []*suite.Status
|
var suiteStatuses []*suite.Status
|
||||||
|
suiteIDs := make(map[*suite.Status]int64) // Track suite_id for each status
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
|
status := &suite.Status{Results: []*suite.Result{}}
|
||||||
var suiteID int64
|
var suiteID int64
|
||||||
var key, name, group string
|
if err = rows.Scan(&suiteID, &status.Key, &status.Name, &status.Group); err != nil {
|
||||||
if err = rows.Scan(&suiteID, &key, &name, &group); err != nil {
|
rows.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
suiteStatuses = append(suiteStatuses, status)
|
||||||
|
suiteIDs[status] = suiteID
|
||||||
|
}
|
||||||
|
rows.Close()
|
||||||
|
|
||||||
status := &suite.Status{
|
for _, status := range suiteStatuses {
|
||||||
Name: name,
|
|
||||||
Group: group,
|
|
||||||
Key: key,
|
|
||||||
Results: []*suite.Result{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get suite results with pagination
|
// Get suite results with pagination
|
||||||
pageSize := 20
|
pageSize := 20
|
||||||
page := 1
|
page := 1
|
||||||
@ -1205,17 +1208,16 @@ func (s *Store) GetAllSuiteStatuses(params *paging.SuiteStatusParams) ([]*suite.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suiteID := suiteIDs[status]
|
||||||
status.Results, err = s.getSuiteResults(tx, suiteID, page, pageSize)
|
status.Results, err = s.getSuiteResults(tx, suiteID, page, pageSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logr.Errorf("[sql.GetAllSuiteStatuses] Failed to retrieve results for suite_id=%d: %s", suiteID, err.Error())
|
logr.Errorf("[sql.GetAllSuiteStatuses] Failed to retrieve results for suite_id=%d: %s", suiteID, err.Error())
|
||||||
}
|
}
|
||||||
// Populate Name and Group fields on each result
|
// Populate Name and Group fields on each result
|
||||||
for _, result := range status.Results {
|
for _, result := range status.Results {
|
||||||
result.Name = name
|
result.Name = status.Name
|
||||||
result.Group = group
|
result.Group = status.Group
|
||||||
}
|
}
|
||||||
|
|
||||||
suiteStatuses = append(suiteStatuses, status)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = tx.Commit(); err != nil {
|
if err = tx.Commit(); err != nil {
|
||||||
@ -1466,7 +1468,6 @@ func (s *Store) getSuiteResults(tx *sql.Tx, suiteID int64, page, pageSize int) (
|
|||||||
logr.Errorf("[sql.getSuiteResults] Query failed: %v", err)
|
logr.Errorf("[sql.getSuiteResults] Query failed: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
|
||||||
type suiteResultData struct {
|
type suiteResultData struct {
|
||||||
result *suite.Result
|
result *suite.Result
|
||||||
id int64
|
id int64
|
||||||
@ -1494,6 +1495,11 @@ func (s *Store) getSuiteResults(tx *sql.Tx, suiteID int64, page, pageSize int) (
|
|||||||
id: suiteResultID,
|
id: suiteResultID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// Close the rows before making nested queries to avoid PostgreSQL driver issues.
|
||||||
|
// The lib/pq driver requires the previous query to be fully closed before starting
|
||||||
|
// new queries in the same transaction, otherwise it returns "pq: unexpected Parse
|
||||||
|
// response 'C'" errors. See: https://github.com/TwiN/gatus/issues/1435
|
||||||
|
rows.Close()
|
||||||
|
|
||||||
// Reverse the results to get chronological order (oldest to newest)
|
// Reverse the results to get chronological order (oldest to newest)
|
||||||
for i := len(resultsData)/2 - 1; i >= 0; i-- {
|
for i := len(resultsData)/2 - 1; i >= 0; i-- {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user