database: use constants to store queries

This commit is contained in:
Quentin Machu 2016-02-22 19:15:38 -05:00 committed by Jimmy Zelinskie
parent 904ce6004f
commit 84319507df
9 changed files with 237 additions and 258 deletions

View File

@ -128,7 +128,7 @@ func TestRaceAffects(t *testing.T) {
featureVersionVersion, _ := strconv.Atoi(featureVersion.Version.String()) featureVersionVersion, _ := strconv.Atoi(featureVersion.Version.String())
// Get actual affects. // Get actual affects.
rows, err := datastore.Query(getQuery("s_complextest_featureversion_affects"), rows, err := datastore.Query(searchComplexTestFeatureVersionAffects,
featureVersion.ID) featureVersion.ID)
assert.Nil(t, err) assert.Nil(t, err)
defer rows.Close() defer rows.Close()

View File

@ -49,9 +49,9 @@ func (pgSQL *pgSQL) insertFeature(feature database.Feature) (int, error) {
// Find or create Feature. // Find or create Feature.
var id int var id int
err = pgSQL.QueryRow(getQuery("soi_feature"), feature.Name, namespaceID).Scan(&id) err = pgSQL.QueryRow(soiFeature, feature.Name, namespaceID).Scan(&id)
if err != nil { if err != nil {
return 0, handleError("soi_feature", err) return 0, handleError("soiFeature", err)
} }
if pgSQL.cache != nil { if pgSQL.cache != nil {
@ -103,25 +103,25 @@ func (pgSQL *pgSQL) insertFeatureVersion(featureVersion database.FeatureVersion)
promConcurrentLockVAFV.Inc() promConcurrentLockVAFV.Inc()
defer promConcurrentLockVAFV.Dec() defer promConcurrentLockVAFV.Dec()
t = time.Now() t = time.Now()
_, err = tx.Exec(getQuery("l_vulnerability_affects_featureversion")) _, err = tx.Exec(lockVulnerabilityAffects)
observeQueryTime("insertFeatureVersion", "lock", t) observeQueryTime("insertFeatureVersion", "lock", t)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return 0, handleError("insertFeatureVersion.l_vulnerability_affects_featureversion", err) return 0, handleError("insertFeatureVersion.lockVulnerabilityAffects", err)
} }
// Find or create FeatureVersion. // Find or create FeatureVersion.
var newOrExisting string var newOrExisting string
t = time.Now() t = time.Now()
err = tx.QueryRow(getQuery("soi_featureversion"), featureID, &featureVersion.Version). err = tx.QueryRow(soiFeatureVersion, featureID, &featureVersion.Version).
Scan(&newOrExisting, &featureVersion.ID) Scan(&newOrExisting, &featureVersion.ID)
observeQueryTime("insertFeatureVersion", "soi_featureversion", t) observeQueryTime("insertFeatureVersion", "soiFeatureVersion", t)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return 0, handleError("soi_featureversion", err) return 0, handleError("soiFeatureVersion", err)
} }
if newOrExisting == "exi" { if newOrExisting == "exi" {
@ -183,9 +183,9 @@ type vulnerabilityAffectsFeatureVersion struct {
func linkFeatureVersionToVulnerabilities(tx *sql.Tx, featureVersion database.FeatureVersion) error { func linkFeatureVersionToVulnerabilities(tx *sql.Tx, featureVersion database.FeatureVersion) error {
// Select every vulnerability and the fixed version that affect this Feature. // Select every vulnerability and the fixed version that affect this Feature.
// TODO(Quentin-M): LIMIT // TODO(Quentin-M): LIMIT
rows, err := tx.Query(getQuery("s_vulnerability_fixedin_feature"), featureVersion.Feature.ID) rows, err := tx.Query(searchVulnerabilityFixedInFeature, featureVersion.Feature.ID)
if err != nil { if err != nil {
return handleError("s_vulnerability_fixedin_feature", err) return handleError("searchVulnerabilityFixedInFeature", err)
} }
defer rows.Close() defer rows.Close()
@ -195,7 +195,7 @@ func linkFeatureVersionToVulnerabilities(tx *sql.Tx, featureVersion database.Fea
err := rows.Scan(&affect.fixedInID, &affect.vulnerabilityID, &affect.fixedInVersion) err := rows.Scan(&affect.fixedInID, &affect.vulnerabilityID, &affect.fixedInVersion)
if err != nil { if err != nil {
return handleError("s_vulnerability_fixedin_feature.Scan()", err) return handleError("searchVulnerabilityFixedInFeature.Scan()", err)
} }
if featureVersion.Version.Compare(affect.fixedInVersion) < 0 { if featureVersion.Version.Compare(affect.fixedInVersion) < 0 {
@ -205,17 +205,17 @@ func linkFeatureVersionToVulnerabilities(tx *sql.Tx, featureVersion database.Fea
} }
} }
if err = rows.Err(); err != nil { if err = rows.Err(); err != nil {
return handleError("s_vulnerability_fixedin_feature.Rows()", err) return handleError("searchVulnerabilityFixedInFeature.Rows()", err)
} }
rows.Close() rows.Close()
// Insert into Vulnerability_Affects_FeatureVersion. // Insert into Vulnerability_Affects_FeatureVersion.
for _, affect := range affects { for _, affect := range affects {
// TODO(Quentin-M): Batch me. // TODO(Quentin-M): Batch me.
_, err := tx.Exec(getQuery("i_vulnerability_affects_featureversion"), affect.vulnerabilityID, _, err := tx.Exec(insertVulnerabilityAffectsFeatureVersion, affect.vulnerabilityID,
featureVersion.ID, affect.fixedInID) featureVersion.ID, affect.fixedInID)
if err != nil { if err != nil {
return handleError("i_vulnerability_affects_featureversion", err) return handleError("insertVulnerabilityAffectsFeatureVersion", err)
} }
} }

View File

@ -41,9 +41,9 @@ func (pgSQL *pgSQL) InsertKeyValue(key, value string) (err error) {
for { for {
// First, try to update. // First, try to update.
r, err := pgSQL.Exec(getQuery("u_keyvalue"), value, key) r, err := pgSQL.Exec(updateKeyValue, value, key)
if err != nil { if err != nil {
return handleError("u_keyvalue", err) return handleError("updateKeyValue", err)
} }
if n, _ := r.RowsAffected(); n > 0 { if n, _ := r.RowsAffected(); n > 0 {
// Updated successfully. // Updated successfully.
@ -52,13 +52,13 @@ func (pgSQL *pgSQL) InsertKeyValue(key, value string) (err error) {
// Try to insert the key. // Try to insert the key.
// If someone else inserts the same key concurrently, we could get a unique-key violation error. // If someone else inserts the same key concurrently, we could get a unique-key violation error.
_, err = pgSQL.Exec(getQuery("i_keyvalue"), key, value) _, err = pgSQL.Exec(insertKeyValue, key, value)
if err != nil { if err != nil {
if isErrUniqueViolation(err) { if isErrUniqueViolation(err) {
// Got unique constraint violation, retry. // Got unique constraint violation, retry.
continue continue
} }
return handleError("i_keyvalue", err) return handleError("insertKeyValue", err)
} }
return nil return nil
@ -70,13 +70,13 @@ func (pgSQL *pgSQL) GetKeyValue(key string) (string, error) {
defer observeQueryTime("GetKeyValue", "all", time.Now()) defer observeQueryTime("GetKeyValue", "all", time.Now())
var value string var value string
err := pgSQL.QueryRow(getQuery("s_keyvalue"), key).Scan(&value) err := pgSQL.QueryRow(searchKeyValue, key).Scan(&value)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return "", nil return "", nil
} }
if err != nil { if err != nil {
return "", handleError("s_keyvalue", err) return "", handleError("searchKeyValue", err)
} }
return value, nil return value, nil

View File

@ -41,13 +41,13 @@ func (pgSQL *pgSQL) FindLayer(name string, withFeatures, withVulnerabilities boo
var namespaceName sql.NullString var namespaceName sql.NullString
t := time.Now() t := time.Now()
err := pgSQL.QueryRow(getQuery("s_layer"), name). err := pgSQL.QueryRow(searchLayer, name).
Scan(&layer.ID, &layer.Name, &layer.EngineVersion, &parentID, &parentName, &namespaceID, Scan(&layer.ID, &layer.Name, &layer.EngineVersion, &parentID, &parentName, &namespaceID,
&namespaceName) &namespaceName)
observeQueryTime("FindLayer", "s_layer", t) observeQueryTime("FindLayer", "searchLayer", t)
if err != nil { if err != nil {
return layer, handleError("s_layer", err) return layer, handleError("searchLayer", err)
} }
if !parentID.IsZero() { if !parentID.IsZero() {
@ -78,11 +78,11 @@ func (pgSQL *pgSQL) FindLayer(name string, withFeatures, withVulnerabilities boo
} }
defer tx.Commit() defer tx.Commit()
_, err = tx.Exec(getQuery("disable_hashjoin")) _, err = tx.Exec(disableHashJoin)
if err != nil { if err != nil {
log.Warningf("FindLayer: could not disable hash join: %s", err) log.Warningf("FindLayer: could not disable hash join: %s", err)
} }
_, err = tx.Exec(getQuery("disable_mergejoin")) _, err = tx.Exec(disableMergeJoin)
if err != nil { if err != nil {
log.Warningf("FindLayer: could not disable merge join: %s", err) log.Warningf("FindLayer: could not disable merge join: %s", err)
} }
@ -117,9 +117,9 @@ func getLayerFeatureVersions(tx *sql.Tx, layerID int) ([]database.FeatureVersion
var featureVersions []database.FeatureVersion var featureVersions []database.FeatureVersion
// Query. // Query.
rows, err := tx.Query(getQuery("s_layer_featureversion"), layerID) rows, err := tx.Query(searchLayerFeatureVersion, layerID)
if err != nil { if err != nil {
return featureVersions, handleError("s_layer_featureversion", err) return featureVersions, handleError("searchLayerFeatureVersion", err)
} }
defer rows.Close() defer rows.Close()
@ -134,7 +134,7 @@ func getLayerFeatureVersions(tx *sql.Tx, layerID int) ([]database.FeatureVersion
&featureVersion.Feature.Name, &featureVersion.ID, &featureVersion.Version, &featureVersion.Feature.Name, &featureVersion.ID, &featureVersion.Version,
&featureVersion.AddedBy.ID, &featureVersion.AddedBy.Name) &featureVersion.AddedBy.ID, &featureVersion.AddedBy.Name)
if err != nil { if err != nil {
return featureVersions, handleError("s_layer_featureversion.Scan()", err) return featureVersions, handleError("searchLayerFeatureVersion.Scan()", err)
} }
// Do transitive closure. // Do transitive closure.
@ -149,7 +149,7 @@ func getLayerFeatureVersions(tx *sql.Tx, layerID int) ([]database.FeatureVersion
} }
} }
if err = rows.Err(); err != nil { if err = rows.Err(); err != nil {
return featureVersions, handleError("s_layer_featureversion.Rows()", err) return featureVersions, handleError("searchLayerFeatureVersion.Rows()", err)
} }
// Build result by converting our map to a slice. // Build result by converting our map to a slice.
@ -173,10 +173,10 @@ func loadAffectedBy(tx *sql.Tx, featureVersions []database.FeatureVersion) error
featureVersionIDs = append(featureVersionIDs, featureVersions[i].ID) featureVersionIDs = append(featureVersionIDs, featureVersions[i].ID)
} }
rows, err := tx.Query(getQuery("s_featureversions_vulnerabilities"), rows, err := tx.Query(searchFeatureVersionVulnerability,
buildInputArray(featureVersionIDs)) buildInputArray(featureVersionIDs))
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
return handleError("s_featureversions_vulnerabilities", err) return handleError("searchFeatureVersionVulnerability", err)
} }
defer rows.Close() defer rows.Close()
@ -188,12 +188,12 @@ func loadAffectedBy(tx *sql.Tx, featureVersions []database.FeatureVersion) error
&vulnerability.Description, &vulnerability.Link, &vulnerability.Severity, &vulnerability.Description, &vulnerability.Link, &vulnerability.Severity,
&vulnerability.Metadata, &vulnerability.Namespace.Name, &vulnerability.FixedBy) &vulnerability.Metadata, &vulnerability.Namespace.Name, &vulnerability.FixedBy)
if err != nil { if err != nil {
return handleError("s_featureversions_vulnerabilities.Scan()", err) return handleError("searchFeatureVersionVulnerability.Scan()", err)
} }
vulnerabilities[featureversionID] = append(vulnerabilities[featureversionID], vulnerability) vulnerabilities[featureversionID] = append(vulnerabilities[featureversionID], vulnerability)
} }
if err = rows.Err(); err != nil { if err = rows.Err(); err != nil {
return handleError("s_featureversions_vulnerabilities.Rows()", err) return handleError("searchFeatureVersionVulnerability.Rows()", err)
} }
// Assign vulnerabilities to every FeatureVersions // Assign vulnerabilities to every FeatureVersions
@ -271,7 +271,7 @@ func (pgSQL *pgSQL) InsertLayer(layer database.Layer) error {
if layer.ID == 0 { if layer.ID == 0 {
// Insert a new layer. // Insert a new layer.
err = tx.QueryRow(getQuery("i_layer"), layer.Name, layer.EngineVersion, parentID, namespaceID). err = tx.QueryRow(insertLayer, layer.Name, layer.EngineVersion, parentID, namespaceID).
Scan(&layer.ID) Scan(&layer.ID)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -280,21 +280,21 @@ func (pgSQL *pgSQL) InsertLayer(layer database.Layer) error {
// Ignore this error, another process collided. // Ignore this error, another process collided.
return nil return nil
} }
return handleError("i_layer", err) return handleError("insertLayer", err)
} }
} else { } else {
// Update an existing layer. // Update an existing layer.
_, err = tx.Exec(getQuery("u_layer"), layer.ID, layer.EngineVersion, namespaceID) _, err = tx.Exec(updateLayer, layer.ID, layer.EngineVersion, namespaceID)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return handleError("u_layer", err) return handleError("updateLayer", err)
} }
// Remove all existing Layer_diff_FeatureVersion. // Remove all existing Layer_diff_FeatureVersion.
_, err = tx.Exec(getQuery("r_layer_diff_featureversion"), layer.ID) _, err = tx.Exec(removeLayerDiffFeatureVersion, layer.ID)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return handleError("r_layer_diff_featureversion", err) return handleError("removeLayerDiffFeatureVersion", err)
} }
} }
@ -355,15 +355,15 @@ func (pgSQL *pgSQL) updateDiffFeatureVersions(tx *sql.Tx, layer, existingLayer *
// Insert diff in the database. // Insert diff in the database.
if len(addIDs) > 0 { if len(addIDs) > 0 {
_, err = tx.Exec(getQuery("i_layer_diff_featureversion"), layer.ID, "add", buildInputArray(addIDs)) _, err = tx.Exec(insertLayerDiffFeatureVersion, layer.ID, "add", buildInputArray(addIDs))
if err != nil { if err != nil {
return handleError("i_layer_diff_featureversion.Add", err) return handleError("insertLayerDiffFeatureVersion.Add", err)
} }
} }
if len(delIDs) > 0 { if len(delIDs) > 0 {
_, err = tx.Exec(getQuery("i_layer_diff_featureversion"), layer.ID, "del", buildInputArray(delIDs)) _, err = tx.Exec(insertLayerDiffFeatureVersion, layer.ID, "del", buildInputArray(delIDs))
if err != nil { if err != nil {
return handleError("i_layer_diff_featureversion.Del", err) return handleError("insertLayerDiffFeatureVersion.Del", err)
} }
} }
@ -387,14 +387,14 @@ func createNV(features []database.FeatureVersion) (map[string]*database.FeatureV
func (pgSQL *pgSQL) DeleteLayer(name string) error { func (pgSQL *pgSQL) DeleteLayer(name string) error {
defer observeQueryTime("DeleteLayer", "all", time.Now()) defer observeQueryTime("DeleteLayer", "all", time.Now())
result, err := pgSQL.Exec(getQuery("r_layer"), name) result, err := pgSQL.Exec(removeLayer, name)
if err != nil { if err != nil {
return handleError("r_layer", err) return handleError("removeLayer", err)
} }
affected, err := result.RowsAffected() affected, err := result.RowsAffected()
if err != nil { if err != nil {
return handleError("r_layer.RowsAffected()", err) return handleError("removeLayer.RowsAffected()", err)
} }
if affected <= 0 { if affected <= 0 {

View File

@ -37,9 +37,9 @@ func (pgSQL *pgSQL) Lock(name string, owner string, duration time.Duration, rene
if renew { if renew {
// Renew lock. // Renew lock.
r, err := pgSQL.Exec(getQuery("u_lock"), name, owner, until) r, err := pgSQL.Exec(updateLock, name, owner, until)
if err != nil { if err != nil {
handleError("u_lock", err) handleError("updateLock", err)
return false, until return false, until
} }
if n, _ := r.RowsAffected(); n > 0 { if n, _ := r.RowsAffected(); n > 0 {
@ -52,10 +52,10 @@ func (pgSQL *pgSQL) Lock(name string, owner string, duration time.Duration, rene
} }
// Lock. // Lock.
_, err := pgSQL.Exec(getQuery("i_lock"), name, owner, until) _, err := pgSQL.Exec(insertLock, name, owner, until)
if err != nil { if err != nil {
if !isErrUniqueViolation(err) { if !isErrUniqueViolation(err) {
handleError("i_lock", err) handleError("insertLock", err)
} }
return false, until return false, until
} }
@ -72,7 +72,7 @@ func (pgSQL *pgSQL) Unlock(name, owner string) {
defer observeQueryTime("Unlock", "all", time.Now()) defer observeQueryTime("Unlock", "all", time.Now())
pgSQL.Exec(getQuery("r_lock"), name, owner) pgSQL.Exec(removeLock, name, owner)
} }
// FindLock returns the owner of a lock specified by its name and its // FindLock returns the owner of a lock specified by its name and its
@ -87,9 +87,9 @@ func (pgSQL *pgSQL) FindLock(name string) (string, time.Time, error) {
var owner string var owner string
var until time.Time var until time.Time
err := pgSQL.QueryRow(getQuery("f_lock"), name).Scan(&owner, &until) err := pgSQL.QueryRow(searchLock, name).Scan(&owner, &until)
if err != nil { if err != nil {
return owner, until, handleError("f_lock", err) return owner, until, handleError("searchLock", err)
} }
return owner, until, nil return owner, until, nil
@ -99,7 +99,7 @@ func (pgSQL *pgSQL) FindLock(name string) (string, time.Time, error) {
func (pgSQL *pgSQL) pruneLocks() { func (pgSQL *pgSQL) pruneLocks() {
defer observeQueryTime("pruneLocks", "all", time.Now()) defer observeQueryTime("pruneLocks", "all", time.Now())
if _, err := pgSQL.Exec(getQuery("r_lock_expired")); err != nil { if _, err := pgSQL.Exec(removeLockExpired); err != nil {
handleError("r_lock_expired", err) handleError("removeLockExpired", err)
} }
} }

View File

@ -38,9 +38,9 @@ func (pgSQL *pgSQL) insertNamespace(namespace database.Namespace) (int, error) {
defer observeQueryTime("insertNamespace", "all", time.Now()) defer observeQueryTime("insertNamespace", "all", time.Now())
var id int var id int
err := pgSQL.QueryRow(getQuery("soi_namespace"), namespace.Name).Scan(&id) err := pgSQL.QueryRow(soiNamespace, namespace.Name).Scan(&id)
if err != nil { if err != nil {
return 0, handleError("soi_namespace", err) return 0, handleError("soiNamespace", err)
} }
if pgSQL.cache != nil { if pgSQL.cache != nil {
@ -51,9 +51,9 @@ func (pgSQL *pgSQL) insertNamespace(namespace database.Namespace) (int, error) {
} }
func (pgSQL *pgSQL) ListNamespaces() (namespaces []database.Namespace, err error) { func (pgSQL *pgSQL) ListNamespaces() (namespaces []database.Namespace, err error) {
rows, err := pgSQL.Query(getQuery("l_namespace")) rows, err := pgSQL.Query(listNamespace)
if err != nil { if err != nil {
return namespaces, handleError("l_namespace", err) return namespaces, handleError("listNamespace", err)
} }
defer rows.Close() defer rows.Close()
@ -62,13 +62,13 @@ func (pgSQL *pgSQL) ListNamespaces() (namespaces []database.Namespace, err error
err = rows.Scan(&namespace.ID, &namespace.Name) err = rows.Scan(&namespace.ID, &namespace.Name)
if err != nil { if err != nil {
return namespaces, handleError("l_namespace.Scan()", err) return namespaces, handleError("listNamespace.Scan()", err)
} }
namespaces = append(namespaces, namespace) namespaces = append(namespaces, namespace)
} }
if err = rows.Err(); err != nil { if err = rows.Err(); err != nil {
return namespaces, handleError("l_namespace.Rows()", err) return namespaces, handleError("listNamespace.Rows()", err)
} }
return namespaces, err return namespaces, err

View File

@ -18,10 +18,10 @@ func createNotification(tx *sql.Tx, oldVulnerabilityID, newVulnerabilityID int)
// Insert Notification. // Insert Notification.
oldVulnerabilityNullableID := sql.NullInt64{Int64: int64(oldVulnerabilityID), Valid: oldVulnerabilityID != 0} oldVulnerabilityNullableID := sql.NullInt64{Int64: int64(oldVulnerabilityID), Valid: oldVulnerabilityID != 0}
newVulnerabilityNullableID := sql.NullInt64{Int64: int64(newVulnerabilityID), Valid: newVulnerabilityID != 0} newVulnerabilityNullableID := sql.NullInt64{Int64: int64(newVulnerabilityID), Valid: newVulnerabilityID != 0}
_, err := tx.Exec(getQuery("i_notification"), uuid.New(), oldVulnerabilityNullableID, newVulnerabilityNullableID) _, err := tx.Exec(insertNotification, uuid.New(), oldVulnerabilityNullableID, newVulnerabilityNullableID)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return handleError("i_notification", err) return handleError("insertNotification", err)
} }
return nil return nil
@ -33,19 +33,19 @@ func (pgSQL *pgSQL) GetAvailableNotification(renotifyInterval time.Duration) (da
defer observeQueryTime("GetAvailableNotification", "all", time.Now()) defer observeQueryTime("GetAvailableNotification", "all", time.Now())
before := time.Now().Add(-renotifyInterval) before := time.Now().Add(-renotifyInterval)
row := pgSQL.QueryRow(getQuery("s_notification_available"), before) row := pgSQL.QueryRow(searchNotificationAvailable, before)
notification, err := pgSQL.scanNotification(row, false) notification, err := pgSQL.scanNotification(row, false)
return notification, handleError("s_notification_available", err) return notification, handleError("searchNotificationAvailable", err)
} }
func (pgSQL *pgSQL) GetNotification(name string, limit int, page database.VulnerabilityNotificationPageNumber) (database.VulnerabilityNotification, database.VulnerabilityNotificationPageNumber, error) { func (pgSQL *pgSQL) GetNotification(name string, limit int, page database.VulnerabilityNotificationPageNumber) (database.VulnerabilityNotification, database.VulnerabilityNotificationPageNumber, error) {
defer observeQueryTime("GetNotification", "all", time.Now()) defer observeQueryTime("GetNotification", "all", time.Now())
// Get Notification. // Get Notification.
notification, err := pgSQL.scanNotification(pgSQL.QueryRow(getQuery("s_notification"), name), true) notification, err := pgSQL.scanNotification(pgSQL.QueryRow(searchNotification, name), true)
if err != nil { if err != nil {
return notification, page, handleError("s_notification", err) return notification, page, handleError("searchNotification", err)
} }
// Load vulnerabilities' LayersIntroducingVulnerability. // Load vulnerabilities' LayersIntroducingVulnerability.
@ -149,10 +149,10 @@ func (pgSQL *pgSQL) loadLayerIntroducingVulnerability(vulnerability *database.Vu
defer observeQueryTime("loadLayerIntroducingVulnerability", "all", tf) defer observeQueryTime("loadLayerIntroducingVulnerability", "all", tf)
// Query with limit + 1, the last item will be used to know the next starting ID. // Query with limit + 1, the last item will be used to know the next starting ID.
rows, err := pgSQL.Query(getQuery("s_notification_layer_introducing_vulnerability"), rows, err := pgSQL.Query(searchNotificationLayerIntroducingVulnerability,
vulnerability.ID, startID, limit+1) vulnerability.ID, startID, limit+1)
if err != nil { if err != nil {
return 0, handleError("s_vulnerability_fixedin_feature", err) return 0, handleError("searchVulnerabilityFixedInFeature", err)
} }
defer rows.Close() defer rows.Close()
@ -161,13 +161,13 @@ func (pgSQL *pgSQL) loadLayerIntroducingVulnerability(vulnerability *database.Vu
var layer database.Layer var layer database.Layer
if err := rows.Scan(&layer.ID, &layer.Name); err != nil { if err := rows.Scan(&layer.ID, &layer.Name); err != nil {
return -1, handleError("s_notification_layer_introducing_vulnerability.Scan()", err) return -1, handleError("searchNotificationLayerIntroducingVulnerability.Scan()", err)
} }
layers = append(layers, layer) layers = append(layers, layer)
} }
if err = rows.Err(); err != nil { if err = rows.Err(); err != nil {
return -1, handleError("s_notification_layer_introducing_vulnerability.Rows()", err) return -1, handleError("searchNotificationLayerIntroducingVulnerability.Rows()", err)
} }
size := limit size := limit
@ -187,8 +187,8 @@ func (pgSQL *pgSQL) loadLayerIntroducingVulnerability(vulnerability *database.Vu
func (pgSQL *pgSQL) SetNotificationNotified(name string) error { func (pgSQL *pgSQL) SetNotificationNotified(name string) error {
defer observeQueryTime("SetNotificationNotified", "all", time.Now()) defer observeQueryTime("SetNotificationNotified", "all", time.Now())
if _, err := pgSQL.Exec(getQuery("u_notification_notified"), name); err != nil { if _, err := pgSQL.Exec(updatedNotificationNotified, name); err != nil {
return handleError("u_notification_notified", err) return handleError("updatedNotificationNotified", err)
} }
return nil return nil
} }
@ -196,14 +196,14 @@ func (pgSQL *pgSQL) SetNotificationNotified(name string) error {
func (pgSQL *pgSQL) DeleteNotification(name string) error { func (pgSQL *pgSQL) DeleteNotification(name string) error {
defer observeQueryTime("DeleteNotification", "all", time.Now()) defer observeQueryTime("DeleteNotification", "all", time.Now())
result, err := pgSQL.Exec(getQuery("r_notification"), name) result, err := pgSQL.Exec(removeNotification, name)
if err != nil { if err != nil {
return handleError("r_notification", err) return handleError("removeNotification", err)
} }
affected, err := result.RowsAffected() affected, err := result.RowsAffected()
if err != nil { if err != nil {
return handleError("r_notification.RowsAffected()", err) return handleError("removeNotification.RowsAffected()", err)
} }
if affected <= 0 { if affected <= 0 {

View File

@ -14,27 +14,20 @@
package pgsql package pgsql
import ( import "strconv"
"fmt"
"strconv"
)
var queries map[string]string const (
lockVulnerabilityAffects = `LOCK Vulnerability_Affects_FeatureVersion IN SHARE ROW EXCLUSIVE MODE`
func init() { disableHashJoin = `SET LOCAL enable_hashjoin = off`
queries = make(map[string]string) disableMergeJoin = `SET LOCAL enable_mergejoin = off`
queries["l_vulnerability_affects_featureversion"] = `LOCK Vulnerability_Affects_FeatureVersion IN SHARE ROW EXCLUSIVE MODE`
queries["disable_hashjoin"] = `SET LOCAL enable_hashjoin = off`
queries["disable_mergejoin"] = `SET LOCAL enable_mergejoin = off`
// keyvalue.go // keyvalue.go
queries["u_keyvalue"] = `UPDATE KeyValue SET value = $1 WHERE key = $2` updateKeyValue = `UPDATE KeyValue SET value = $1 WHERE key = $2`
queries["i_keyvalue"] = `INSERT INTO KeyValue(key, value) VALUES($1, $2)` insertKeyValue = `INSERT INTO KeyValue(key, value) VALUES($1, $2)`
queries["s_keyvalue"] = `SELECT value FROM KeyValue WHERE key = $1` searchKeyValue = `SELECT value FROM KeyValue WHERE key = $1`
// namespace.go // namespace.go
queries["soi_namespace"] = ` soiNamespace = `
WITH new_namespace AS ( WITH new_namespace AS (
INSERT INTO Namespace(name) INSERT INTO Namespace(name)
SELECT CAST($1 AS VARCHAR) SELECT CAST($1 AS VARCHAR)
@ -45,10 +38,10 @@ func init() {
UNION UNION
SELECT id FROM new_namespace` SELECT id FROM new_namespace`
queries["l_namespace"] = `SELECT id, name FROM Namespace` listNamespace = `SELECT id, name FROM Namespace`
// feature.go // feature.go
queries["soi_feature"] = ` soiFeature = `
WITH new_feature AS ( WITH new_feature AS (
INSERT INTO Feature(name, namespace_id) INSERT INTO Feature(name, namespace_id)
SELECT CAST($1 AS VARCHAR), CAST($2 AS INTEGER) SELECT CAST($1 AS VARCHAR), CAST($2 AS INTEGER)
@ -59,7 +52,7 @@ func init() {
UNION UNION
SELECT id FROM new_feature` SELECT id FROM new_feature`
queries["soi_featureversion"] = ` soiFeatureVersion = `
WITH new_featureversion AS ( WITH new_featureversion AS (
INSERT INTO FeatureVersion(feature_id, version) INSERT INTO FeatureVersion(feature_id, version)
SELECT CAST($1 AS INTEGER), CAST($2 AS VARCHAR) SELECT CAST($1 AS INTEGER), CAST($2 AS VARCHAR)
@ -68,26 +61,25 @@ func init() {
) )
SELECT 'exi', id FROM FeatureVersion WHERE feature_id = $1 AND version = $2 SELECT 'exi', id FROM FeatureVersion WHERE feature_id = $1 AND version = $2
UNION UNION
SELECT 'new', id FROM new_featureversion SELECT 'new', id FROM new_featureversion`
`
queries["s_vulnerability_fixedin_feature"] = ` searchVulnerabilityFixedInFeature = `
SELECT id, vulnerability_id, version FROM Vulnerability_FixedIn_Feature SELECT id, vulnerability_id, version FROM Vulnerability_FixedIn_Feature
WHERE feature_id = $1` WHERE feature_id = $1`
queries["i_vulnerability_affects_featureversion"] = ` insertVulnerabilityAffectsFeatureVersion = `
INSERT INTO Vulnerability_Affects_FeatureVersion(vulnerability_id, INSERT INTO Vulnerability_Affects_FeatureVersion(vulnerability_id,
featureversion_id, fixedin_id) VALUES($1, $2, $3)` featureversion_id, fixedin_id) VALUES($1, $2, $3)`
// layer.go // layer.go
queries["s_layer"] = ` searchLayer = `
SELECT l.id, l.name, l.engineversion, p.id, p.name, n.id, n.name SELECT l.id, l.name, l.engineversion, p.id, p.name, n.id, n.name
FROM Layer l FROM Layer l
LEFT JOIN Layer p ON l.parent_id = p.id LEFT JOIN Layer p ON l.parent_id = p.id
LEFT JOIN Namespace n ON l.namespace_id = n.id LEFT JOIN Namespace n ON l.namespace_id = n.id
WHERE l.name = $1;` WHERE l.name = $1;`
queries["s_layer_featureversion"] = ` searchLayerFeatureVersion = `
WITH RECURSIVE layer_tree(id, name, parent_id, depth, path, cycle) AS( WITH RECURSIVE layer_tree(id, name, parent_id, depth, path, cycle) AS(
SELECT l.id, l.name, l.parent_id, 1, ARRAY[l.id], false SELECT l.id, l.name, l.parent_id, 1, ARRAY[l.id], false
FROM Layer l FROM Layer l
@ -105,7 +97,7 @@ func init() {
WHERE ldf.featureversion_id = fv.id AND fv.feature_id = f.id AND f.namespace_id = fn.id WHERE ldf.featureversion_id = fv.id AND fv.feature_id = f.id AND f.namespace_id = fn.id
ORDER BY ltree.ordering` ORDER BY ltree.ordering`
queries["s_featureversions_vulnerabilities"] = ` searchFeatureVersionVulnerability = `
SELECT vafv.featureversion_id, v.id, v.name, v.description, v.link, v.severity, v.metadata, SELECT vafv.featureversion_id, v.id, v.name, v.description, v.link, v.severity, v.metadata,
vn.name, vfif.version vn.name, vfif.version
FROM Vulnerability_Affects_FeatureVersion vafv, Vulnerability v, FROM Vulnerability_Affects_FeatureVersion vafv, Vulnerability v,
@ -116,64 +108,58 @@ func init() {
AND v.namespace_id = vn.id AND v.namespace_id = vn.id
AND v.deleted_at IS NULL` AND v.deleted_at IS NULL`
queries["i_layer"] = ` insertLayer = `
INSERT INTO Layer(name, engineversion, parent_id, namespace_id, created_at) INSERT INTO Layer(name, engineversion, parent_id, namespace_id, created_at)
VALUES($1, $2, $3, $4, CURRENT_TIMESTAMP) VALUES($1, $2, $3, $4, CURRENT_TIMESTAMP)
RETURNING id` RETURNING id`
queries["u_layer"] = `UPDATE LAYER SET engineversion = $2, namespace_id = $3 WHERE id = $1` updateLayer = `UPDATE LAYER SET engineversion = $2, namespace_id = $3 WHERE id = $1`
queries["r_layer_diff_featureversion"] = ` removeLayerDiffFeatureVersion = `
DELETE FROM Layer_diff_FeatureVersion DELETE FROM Layer_diff_FeatureVersion
WHERE layer_id = $1` WHERE layer_id = $1`
queries["i_layer_diff_featureversion"] = ` insertLayerDiffFeatureVersion = `
INSERT INTO Layer_diff_FeatureVersion(layer_id, featureversion_id, modification) INSERT INTO Layer_diff_FeatureVersion(layer_id, featureversion_id, modification)
SELECT $1, fv.id, $2 SELECT $1, fv.id, $2
FROM FeatureVersion fv FROM FeatureVersion fv
WHERE fv.id = ANY($3::integer[])` WHERE fv.id = ANY($3::integer[])`
queries["r_layer"] = `DELETE FROM Layer WHERE name = $1` removeLayer = `DELETE FROM Layer WHERE name = $1`
// lock.go // lock.go
queries["i_lock"] = `INSERT INTO Lock(name, owner, until) VALUES($1, $2, $3)` insertLock = `INSERT INTO Lock(name, owner, until) VALUES($1, $2, $3)`
searchLock = `SELECT owner, until FROM Lock WHERE name = $1`
queries["f_lock"] = `SELECT owner, until FROM Lock WHERE name = $1` updateLock = `UPDATE Lock SET until = $3 WHERE name = $1 AND owner = $2`
removeLock = `DELETE FROM Lock WHERE name = $1 AND owner = $2`
queries["u_lock"] = `UPDATE Lock SET until = $3 WHERE name = $1 AND owner = $2` removeLockExpired = `DELETE FROM LOCK WHERE until < CURRENT_TIMESTAMP`
queries["r_lock"] = `DELETE FROM Lock WHERE name = $1 AND owner = $2`
queries["r_lock_expired"] = `DELETE FROM LOCK WHERE until < CURRENT_TIMESTAMP`
// vulnerability.go // vulnerability.go
queries["f_vulnerability_base"] = ` searchVulnerabilityBase = `
SELECT v.id, v.name, n.id, n.name, v.description, v.link, v.severity, v.metadata SELECT v.id, v.name, n.id, n.name, v.description, v.link, v.severity, v.metadata
FROM Vulnerability v JOIN Namespace n ON v.namespace_id = n.id` FROM Vulnerability v JOIN Namespace n ON v.namespace_id = n.id`
searchVulnerabilityForUpdate = ` FOR UPDATE OF v`
searchVulnerabilityByNamespaceAndName = ` WHERE n.name = $1 AND v.name = $2 AND v.deleted_at IS NULL`
searchVulnerabilityByID = ` WHERE v.id = $1`
queries["f_vulnerability_for_update"] = ` FOR UPDATE OF v` searchVulnerabilityFixedIn = `
queries["f_vulnerability_+by_name_namespace"] = ` WHERE n.name = $1 AND v.name = $2 AND v.deleted_at IS NULL`
queries["f_vulnerability_+by_id"] = ` WHERE v.id = $1`
queries["f_vulnerability_fixedin"] = `
SELECT vfif.version, f.id, f.Name SELECT vfif.version, f.id, f.Name
FROM Vulnerability_FixedIn_Feature vfif JOIN Feature f ON vfif.feature_id = f.id FROM Vulnerability_FixedIn_Feature vfif JOIN Feature f ON vfif.feature_id = f.id
WHERE vfif.vulnerability_id = $1` WHERE vfif.vulnerability_id = $1`
queries["i_vulnerability"] = ` insertVulnerability = `
INSERT INTO Vulnerability(namespace_id, name, description, link, severity, metadata, created_at) INSERT INTO Vulnerability(namespace_id, name, description, link, severity, metadata, created_at)
VALUES($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP) VALUES($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP)
RETURNING id` RETURNING id`
queries["i_vulnerability_fixedin_feature"] = ` insertVulnerabilityFixedInFeature = `
INSERT INTO Vulnerability_FixedIn_Feature(vulnerability_id, feature_id, version) INSERT INTO Vulnerability_FixedIn_Feature(vulnerability_id, feature_id, version)
VALUES($1, $2, $3) VALUES($1, $2, $3)
RETURNING id` RETURNING id`
queries["f_featureversion_by_feature"] = ` searchFeatureVersionByFeature = `SELECT id, version FROM FeatureVersion WHERE feature_id = $1`
SELECT id, version FROM FeatureVersion WHERE feature_id = $1`
queries["r_vulnerability"] = ` removeVulnerability = `
UPDATE Vulnerability UPDATE Vulnerability
SET deleted_at = CURRENT_TIMESTAMP SET deleted_at = CURRENT_TIMESTAMP
WHERE namespace_id = (SELECT id FROM Namespace WHERE name = $1) WHERE namespace_id = (SELECT id FROM Namespace WHERE name = $1)
@ -182,21 +168,21 @@ func init() {
RETURNING id` RETURNING id`
// notification.go // notification.go
queries["i_notification"] = ` insertNotification = `
INSERT INTO Vulnerability_Notification(name, created_at, old_vulnerability_id, new_vulnerability_id) INSERT INTO Vulnerability_Notification(name, created_at, old_vulnerability_id, new_vulnerability_id)
VALUES($1, CURRENT_TIMESTAMP, $2, $3)` VALUES($1, CURRENT_TIMESTAMP, $2, $3)`
queries["u_notification_notified"] = ` updatedNotificationNotified = `
UPDATE Vulnerability_Notification UPDATE Vulnerability_Notification
SET notified_at = CURRENT_TIMESTAMP SET notified_at = CURRENT_TIMESTAMP
WHERE name = $1` WHERE name = $1`
queries["r_notification"] = ` removeNotification = `
UPDATE Vulnerability_Notification UPDATE Vulnerability_Notification
SET deleted_at = CURRENT_TIMESTAMP SET deleted_at = CURRENT_TIMESTAMP
WHERE name = $1` WHERE name = $1`
queries["s_notification_available"] = ` searchNotificationAvailable = `
SELECT id, name, created_at, notified_at, deleted_at SELECT id, name, created_at, notified_at, deleted_at
FROM Vulnerability_Notification FROM Vulnerability_Notification
WHERE (notified_at IS NULL OR notified_at < $1) WHERE (notified_at IS NULL OR notified_at < $1)
@ -205,12 +191,12 @@ func init() {
ORDER BY Random() ORDER BY Random()
LIMIT 1` LIMIT 1`
queries["s_notification"] = ` searchNotification = `
SELECT id, name, created_at, notified_at, deleted_at, old_vulnerability_id, new_vulnerability_id SELECT id, name, created_at, notified_at, deleted_at, old_vulnerability_id, new_vulnerability_id
FROM Vulnerability_Notification FROM Vulnerability_Notification
WHERE name = $1` WHERE name = $1`
queries["s_notification_layer_introducing_vulnerability"] = ` searchNotificationLayerIntroducingVulnerability = `
SELECT l.ID, l.name SELECT l.ID, l.name
FROM Vulnerability v, Vulnerability_Affects_FeatureVersion vafv, FeatureVersion fv, Layer_diff_FeatureVersion ldfv, Layer l FROM Vulnerability v, Vulnerability_Affects_FeatureVersion vafv, FeatureVersion fv, Layer_diff_FeatureVersion ldfv, Layer l
WHERE v.id = $1 WHERE v.id = $1
@ -224,20 +210,13 @@ func init() {
LIMIT $3` LIMIT $3`
// complex_test.go // complex_test.go
queries["s_complextest_featureversion_affects"] = ` searchComplexTestFeatureVersionAffects = `
SELECT v.name SELECT v.name
FROM FeatureVersion fv FROM FeatureVersion fv
LEFT JOIN Vulnerability_Affects_FeatureVersion vaf ON fv.id = vaf.featureversion_id LEFT JOIN Vulnerability_Affects_FeatureVersion vaf ON fv.id = vaf.featureversion_id
JOIN Vulnerability v ON vaf.vulnerability_id = v.id JOIN Vulnerability v ON vaf.vulnerability_id = v.id
WHERE featureversion_id = $1` WHERE featureversion_id = $1`
} )
func getQuery(name string) string {
if query, ok := queries[name]; ok {
return query
}
panic(fmt.Sprintf("pgsql: unknown query %v", name))
}
// buildInputArray constructs a PostgreSQL input array from the specified integers. // buildInputArray constructs a PostgreSQL input array from the specified integers.
// Useful to use the `= ANY($1::integer[])` syntax that let us use a IN clause while using // Useful to use the `= ANY($1::integer[])` syntax that let us use a IN clause while using

View File

@ -35,11 +35,11 @@ func (pgSQL *pgSQL) FindVulnerability(namespaceName, name string) (database.Vuln
func findVulnerability(queryer Queryer, namespaceName, name string, forUpdate bool) (database.Vulnerability, error) { func findVulnerability(queryer Queryer, namespaceName, name string, forUpdate bool) (database.Vulnerability, error) {
defer observeQueryTime("findVulnerability", "all", time.Now()) defer observeQueryTime("findVulnerability", "all", time.Now())
queryName := "f_vulnerability" queryName := "searchVulnerabilityBase+searchVulnerabilityByNamespaceAndName"
query := getQuery("f_vulnerability_base") + getQuery("f_vulnerability_+by_name_namespace") query := searchVulnerabilityBase + searchVulnerabilityByNamespaceAndName
if forUpdate { if forUpdate {
queryName = queryName + "+for_update" queryName = queryName + "+searchVulnerabilityForUpdate"
query = query + getQuery("f_vulnerability_for_update") query = query + searchVulnerabilityForUpdate
} }
return scanVulnerability(queryer, queryName, queryer.QueryRow(query, namespaceName, name)) return scanVulnerability(queryer, queryName, queryer.QueryRow(query, namespaceName, name))
@ -48,8 +48,8 @@ func findVulnerability(queryer Queryer, namespaceName, name string, forUpdate bo
func (pgSQL *pgSQL) findVulnerabilityByIDWithDeleted(id int) (database.Vulnerability, error) { func (pgSQL *pgSQL) findVulnerabilityByIDWithDeleted(id int) (database.Vulnerability, error) {
defer observeQueryTime("findVulnerabilityByIDWithDeleted", "all", time.Now()) defer observeQueryTime("findVulnerabilityByIDWithDeleted", "all", time.Now())
queryName := "f_vulnerability" queryName := "searchVulnerabilityBase+searchVulnerabilityByID"
query := getQuery("f_vulnerability_base") + getQuery("f_vulnerability_+by_id") query := searchVulnerabilityBase + searchVulnerabilityByID
return scanVulnerability(pgSQL, queryName, pgSQL.QueryRow(query, id)) return scanVulnerability(pgSQL, queryName, pgSQL.QueryRow(query, id))
} }
@ -77,9 +77,9 @@ func scanVulnerability(queryer Queryer, queryName string, vulnerabilityRow *sql.
} }
// Query the FixedIn FeatureVersion now. // Query the FixedIn FeatureVersion now.
rows, err := queryer.Query(getQuery("f_vulnerability_fixedin"), vulnerability.ID) rows, err := queryer.Query(searchVulnerabilityFixedIn, vulnerability.ID)
if err != nil { if err != nil {
return vulnerability, handleError("f_vulnerability_fixedin.Scan()", err) return vulnerability, handleError("searchVulnerabilityFixedIn.Scan()", err)
} }
defer rows.Close() defer rows.Close()
@ -95,7 +95,7 @@ func scanVulnerability(queryer Queryer, queryName string, vulnerabilityRow *sql.
) )
if err != nil { if err != nil {
return vulnerability, handleError("f_vulnerability_fixedin.Scan()", err) return vulnerability, handleError("searchVulnerabilityFixedIn.Scan()", err)
} }
if !featureVersionID.IsZero() { if !featureVersionID.IsZero() {
@ -115,7 +115,7 @@ func scanVulnerability(queryer Queryer, queryName string, vulnerabilityRow *sql.
} }
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {
return vulnerability, handleError("f_vulnerability_fixedin.Rows()", err) return vulnerability, handleError("searchVulnerabilityFixedIn.Rows()", err)
} }
return vulnerability, nil return vulnerability, nil
@ -209,10 +209,10 @@ func (pgSQL *pgSQL) insertVulnerability(vulnerability database.Vulnerability, on
} }
// Mark the old vulnerability as non latest. // Mark the old vulnerability as non latest.
_, err = tx.Exec(getQuery("r_vulnerability"), vulnerability.Namespace.Name, vulnerability.Name) _, err = tx.Exec(removeVulnerability, vulnerability.Namespace.Name, vulnerability.Name)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return handleError("r_vulnerability", err) return handleError("removeVulnerability", err)
} }
} else { } else {
// The vulnerability is new, we don't want to have any types.MinVersion as they are only used // The vulnerability is new, we don't want to have any types.MinVersion as they are only used
@ -234,7 +234,7 @@ func (pgSQL *pgSQL) insertVulnerability(vulnerability database.Vulnerability, on
// Insert vulnerability. // Insert vulnerability.
err = tx.QueryRow( err = tx.QueryRow(
getQuery("i_vulnerability"), insertVulnerability,
namespaceID, namespaceID,
vulnerability.Name, vulnerability.Name,
vulnerability.Description, vulnerability.Description,
@ -245,7 +245,7 @@ func (pgSQL *pgSQL) insertVulnerability(vulnerability database.Vulnerability, on
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return handleError("i_vulnerability", err) return handleError("insertVulnerability", err)
} }
// Update Vulnerability_FixedIn_Feature and Vulnerability_Affects_FeatureVersion now. // Update Vulnerability_FixedIn_Feature and Vulnerability_Affects_FeatureVersion now.
@ -368,12 +368,12 @@ func (pgSQL *pgSQL) insertVulnerabilityFixedInFeatureVersions(tx *sql.Tx, vulner
promConcurrentLockVAFV.Inc() promConcurrentLockVAFV.Inc()
defer promConcurrentLockVAFV.Dec() defer promConcurrentLockVAFV.Dec()
t := time.Now() t := time.Now()
_, err = tx.Exec(getQuery("l_vulnerability_affects_featureversion")) _, err = tx.Exec(lockVulnerabilityAffects)
observeQueryTime("insertVulnerability", "lock", t) observeQueryTime("insertVulnerability", "lock", t)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return handleError("insertVulnerability.l_vulnerability_affects_featureversion", err) return handleError("insertVulnerability.lockVulnerabilityAffects", err)
} }
for _, fv := range fixedIn { for _, fv := range fixedIn {
@ -381,13 +381,13 @@ func (pgSQL *pgSQL) insertVulnerabilityFixedInFeatureVersions(tx *sql.Tx, vulner
// Insert Vulnerability_FixedIn_Feature. // Insert Vulnerability_FixedIn_Feature.
err = tx.QueryRow( err = tx.QueryRow(
getQuery("i_vulnerability_fixedin_feature"), insertVulnerabilityFixedInFeature,
vulnerabilityID, fv.Feature.ID, vulnerabilityID, fv.Feature.ID,
&fv.Version, &fv.Version,
).Scan(&fixedInID) ).Scan(&fixedInID)
if err != nil { if err != nil {
return handleError("i_vulnerability_fixedin_feature", err) return handleError("insertVulnerabilityFixedInFeature", err)
} }
// Insert Vulnerability_Affects_FeatureVersion. // Insert Vulnerability_Affects_FeatureVersion.
@ -403,9 +403,9 @@ func (pgSQL *pgSQL) insertVulnerabilityFixedInFeatureVersions(tx *sql.Tx, vulner
func linkVulnerabilityToFeatureVersions(tx *sql.Tx, fixedInID, vulnerabilityID, featureID int, fixedInVersion types.Version) error { func linkVulnerabilityToFeatureVersions(tx *sql.Tx, fixedInID, vulnerabilityID, featureID int, fixedInVersion types.Version) error {
// Find every FeatureVersions of the Feature that the vulnerability affects. // Find every FeatureVersions of the Feature that the vulnerability affects.
// TODO(Quentin-M): LIMIT // TODO(Quentin-M): LIMIT
rows, err := tx.Query(getQuery("f_featureversion_by_feature"), featureID) rows, err := tx.Query(searchFeatureVersionByFeature, featureID)
if err != nil { if err != nil {
return handleError("f_featureversion_by_feature", err) return handleError("searchFeatureVersionByFeature", err)
} }
defer rows.Close() defer rows.Close()
@ -415,7 +415,7 @@ func linkVulnerabilityToFeatureVersions(tx *sql.Tx, fixedInID, vulnerabilityID,
err := rows.Scan(&affected.ID, &affected.Version) err := rows.Scan(&affected.ID, &affected.Version)
if err != nil { if err != nil {
return handleError("f_featureversion_by_feature.Scan()", err) return handleError("searchFeatureVersionByFeature.Scan()", err)
} }
if affected.Version.Compare(fixedInVersion) < 0 { if affected.Version.Compare(fixedInVersion) < 0 {
@ -425,17 +425,17 @@ func linkVulnerabilityToFeatureVersions(tx *sql.Tx, fixedInID, vulnerabilityID,
} }
} }
if err = rows.Err(); err != nil { if err = rows.Err(); err != nil {
return handleError("f_featureversion_by_feature.Rows()", err) return handleError("searchFeatureVersionByFeature.Rows()", err)
} }
rows.Close() rows.Close()
// Insert into Vulnerability_Affects_FeatureVersion. // Insert into Vulnerability_Affects_FeatureVersion.
for _, affected := range affecteds { for _, affected := range affecteds {
// TODO(Quentin-M): Batch me. // TODO(Quentin-M): Batch me.
_, err := tx.Exec(getQuery("i_vulnerability_affects_featureversion"), vulnerabilityID, _, err := tx.Exec(insertVulnerabilityAffectsFeatureVersion, vulnerabilityID,
affected.ID, fixedInID) affected.ID, fixedInID)
if err != nil { if err != nil {
return handleError("i_vulnerability_affects_featureversion", err) return handleError("insertVulnerabilityAffectsFeatureVersion", err)
} }
} }
@ -491,10 +491,10 @@ func (pgSQL *pgSQL) DeleteVulnerability(namespaceName, name string) error {
} }
var vulnerabilityID int var vulnerabilityID int
err = tx.QueryRow(getQuery("r_vulnerability"), namespaceName, name).Scan(&vulnerabilityID) err = tx.QueryRow(removeVulnerability, namespaceName, name).Scan(&vulnerabilityID)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return handleError("r_vulnerability", err) return handleError("removeVulnerability", err)
} }
// Create a notification. // Create a notification.