github.com/quay/claircore@v1.5.28/datastore/postgres/repositoriesbylayer.go (about) 1 package postgres 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "strconv" 8 "time" 9 10 "github.com/jackc/pgx/v4" 11 "github.com/prometheus/client_golang/prometheus" 12 "github.com/prometheus/client_golang/prometheus/promauto" 13 14 "github.com/quay/claircore" 15 "github.com/quay/claircore/indexer" 16 ) 17 18 var ( 19 repositoriesByLayerCounter = promauto.NewCounterVec( 20 prometheus.CounterOpts{ 21 Namespace: "claircore", 22 Subsystem: "indexer", 23 Name: "repositoriesbylayer_total", 24 Help: "Total number of database queries issued in the RepositoriesByLayer method.", 25 }, 26 []string{"query"}, 27 ) 28 29 repositoriesByLayerDuration = promauto.NewHistogramVec( 30 prometheus.HistogramOpts{ 31 Namespace: "claircore", 32 Subsystem: "indexer", 33 Name: "repositoriesbylayer_duration_seconds", 34 Help: "The duration of all queries issued in the RepositoriesByLayer method", 35 }, 36 []string{"query"}, 37 ) 38 ) 39 40 func (s *IndexerStore) RepositoriesByLayer(ctx context.Context, hash claircore.Digest, scnrs indexer.VersionedScanners) ([]*claircore.Repository, error) { 41 const query = ` 42 SELECT 43 repo.id, repo.name, repo.key, repo.uri, repo.cpe 44 FROM 45 repo_scanartifact 46 LEFT JOIN repo ON repo_scanartifact.repo_id = repo.id 47 JOIN layer ON layer.hash = $1 48 WHERE 49 repo_scanartifact.layer_id = layer.id 50 AND repo_scanartifact.scanner_id = ANY ($2); 51 ` 52 53 if len(scnrs) == 0 { 54 return []*claircore.Repository{}, nil 55 } 56 scannerIDs, err := s.selectScanners(ctx, scnrs) 57 if err != nil { 58 return nil, fmt.Errorf("unable to select scanners: %w", err) 59 } 60 61 start := time.Now() 62 rows, err := s.pool.Query(ctx, query, hash, scannerIDs) 63 switch { 64 case errors.Is(err, nil): 65 case errors.Is(err, pgx.ErrNoRows): 66 return nil, fmt.Errorf("no repositories found for layer, scanners set") 67 default: 68 return nil, fmt.Errorf("failed to retrieve repositories for layer, scanners set: %w", err) 69 } 70 repositoriesByLayerCounter.WithLabelValues("query").Add(1) 71 repositoriesByLayerDuration.WithLabelValues("query").Observe(time.Since(start).Seconds()) 72 defer rows.Close() 73 74 res := []*claircore.Repository{} 75 for rows.Next() { 76 var repo claircore.Repository 77 78 var id int64 79 err := rows.Scan( 80 &id, 81 &repo.Name, 82 &repo.Key, 83 &repo.URI, 84 &repo.CPE, 85 ) 86 repo.ID = strconv.FormatInt(id, 10) 87 if err != nil { 88 return nil, fmt.Errorf("failed to scan repositories: %w", err) 89 } 90 91 res = append(res, &repo) 92 } 93 if err := rows.Err(); err != nil { 94 return nil, err 95 } 96 97 return res, nil 98 }