@@ -51,7 +51,7 @@ func (s *MatcherStore) Get(ctx context.Context, records []*claircore.IndexRecord
5151 defer tx .Rollback (ctx )
5252 // start a batch
5353 batch := & pgx.Batch {}
54- resCache := map [string ]pgx. Rows {}
54+ resCache := map [string ][] * claircore. Vulnerability {}
5555 rqs := []* recordQuery {}
5656 for _ , record := range records {
5757 query , err := buildGetQuery (record , & opts )
@@ -72,7 +72,6 @@ func (s *MatcherStore) Get(ctx context.Context, records []*claircore.IndexRecord
7272 resCache [query ] = nil
7373 }
7474 // send the batch
75-
7675 start := time .Now ()
7776 res := tx .SendBatch (ctx , batch )
7877 // Can't just defer the close, because the batch must be fully handled
@@ -83,72 +82,89 @@ func (s *MatcherStore) Get(ctx context.Context, records []*claircore.IndexRecord
8382 results := make (map [string ][]* claircore.Vulnerability )
8483 vulnSet := make (map [string ]map [string ]struct {})
8584 for _ , rq := range rqs {
86- rows , ok := resCache [rq .query ]
85+ rid := rq .record .Package .ID
86+ vulns , ok := resCache [rq .query ]
8787 if ! ok {
8888 return nil , fmt .Errorf ("unexpected vulnerability query: %s" , rq .query )
8989 }
90- if rows == nil {
91- rows , err = res .Query ()
92- if err != nil {
93- res .Close ()
94- return nil , err
90+ if vulns != nil { // We already have results we don't need to go back to the DB.
91+ if _ , ok := vulnSet [rid ]; ! ok {
92+ vulnSet [rid ] = make (map [string ]struct {})
9593 }
96- resCache [rq .query ] = rows
97- }
98-
99- // unpack all returned rows into claircore.Vulnerability structs
100- for rows .Next () {
101- // fully allocate vuln struct
102- v := & claircore.Vulnerability {
103- Package : & claircore.Package {},
104- Dist : & claircore.Distribution {},
105- Repo : & claircore.Repository {},
94+ for _ , v := range vulns {
95+ if _ , ok := vulnSet [rid ][v.ID ]; ! ok {
96+ vulnSet [rid ][v.ID ] = struct {}{}
97+ results [rid ] = append (results [rid ], v )
98+ }
10699 }
107-
108- var id int64
109- err := rows .Scan (
110- & id ,
111- & v .Name ,
112- & v .Description ,
113- & v .Issued ,
114- & v .Links ,
115- & v .Severity ,
116- & v .NormalizedSeverity ,
117- & v .Package .Name ,
118- & v .Package .Version ,
119- & v .Package .Module ,
120- & v .Package .Arch ,
121- & v .Package .Kind ,
122- & v .Dist .DID ,
123- & v .Dist .Name ,
124- & v .Dist .Version ,
125- & v .Dist .VersionCodeName ,
126- & v .Dist .VersionID ,
127- & v .Dist .Arch ,
128- & v .Dist .CPE ,
129- & v .Dist .PrettyName ,
130- & v .ArchOperation ,
131- & v .Repo .Name ,
132- & v .Repo .Key ,
133- & v .Repo .URI ,
134- & v .FixedInVersion ,
135- & v .Updater ,
136- )
137- v .ID = strconv .FormatInt (id , 10 )
100+ continue
101+ }
102+ results [rid ] = []* claircore.Vulnerability {}
103+ err := func () error {
104+ rows , err := res .Query ()
138105 if err != nil {
139106 res .Close ()
140- return nil , fmt .Errorf ("failed to scan vulnerability : %v " , err )
107+ return fmt .Errorf ("error getting rows : %w " , err )
141108 }
109+ defer rows .Close ()
110+ // unpack all returned rows into claircore.Vulnerability structs
111+ for rows .Next () {
112+ // fully allocate vuln struct
113+ v := & claircore.Vulnerability {
114+ Package : & claircore.Package {},
115+ Dist : & claircore.Distribution {},
116+ Repo : & claircore.Repository {},
117+ }
142118
143- rid := rq .record .Package .ID
144- if _ , ok := vulnSet [rid ]; ! ok {
145- vulnSet [rid ] = make (map [string ]struct {})
146- }
147- if _ , ok := vulnSet [rid ][v.ID ]; ! ok {
148- vulnSet [rid ][v.ID ] = struct {}{}
149- results [rid ] = append (results [rid ], v )
119+ var id int64
120+ err := rows .Scan (
121+ & id ,
122+ & v .Name ,
123+ & v .Description ,
124+ & v .Issued ,
125+ & v .Links ,
126+ & v .Severity ,
127+ & v .NormalizedSeverity ,
128+ & v .Package .Name ,
129+ & v .Package .Version ,
130+ & v .Package .Module ,
131+ & v .Package .Arch ,
132+ & v .Package .Kind ,
133+ & v .Dist .DID ,
134+ & v .Dist .Name ,
135+ & v .Dist .Version ,
136+ & v .Dist .VersionCodeName ,
137+ & v .Dist .VersionID ,
138+ & v .Dist .Arch ,
139+ & v .Dist .CPE ,
140+ & v .Dist .PrettyName ,
141+ & v .ArchOperation ,
142+ & v .Repo .Name ,
143+ & v .Repo .Key ,
144+ & v .Repo .URI ,
145+ & v .FixedInVersion ,
146+ & v .Updater ,
147+ )
148+ v .ID = strconv .FormatInt (id , 10 )
149+ if err != nil {
150+ res .Close ()
151+ return fmt .Errorf ("failed to scan vulnerability: %w" , err )
152+ }
153+
154+ if _ , ok := vulnSet [rid ]; ! ok {
155+ vulnSet [rid ] = make (map [string ]struct {})
156+ }
157+ if _ , ok := vulnSet [rid ][v.ID ]; ! ok {
158+ vulnSet [rid ][v.ID ] = struct {}{}
159+ results [rid ] = append (results [rid ], v )
160+ }
150161 }
162+ return nil
163+ }()
164+ if err != nil {
165+ return nil , err
151166 }
167+ resCache [rq .query ] = results [rid ]
152168 }
153169 if err := res .Close (); err != nil {
154170 return nil , fmt .Errorf ("some weird batch error: %v" , err )
0 commit comments