Merge pull request #263 from Quentin-M/rhel_unique_fixedin

pgsql: Do not insert entry in Vulnerability_FixedIn_Feature if existing
This commit is contained in:
Quentin Machu 2016-11-13 13:25:08 +01:00 committed by Jimmy Zelinskie
parent 5157f27eac
commit 94bcf91cdf
4 changed files with 36 additions and 23 deletions

View File

@ -129,11 +129,11 @@ func (pgSQL *pgSQL) insertFeatureVersion(featureVersion database.FeatureVersion)
} }
// Find or create FeatureVersion. // Find or create FeatureVersion.
var newOrExisting string var created bool
t = time.Now() t = time.Now()
err = tx.QueryRow(soiFeatureVersion, featureID, &featureVersion.Version). err = tx.QueryRow(soiFeatureVersion, featureID, &featureVersion.Version).
Scan(&newOrExisting, &featureVersion.ID) Scan(&created, &featureVersion.ID)
observeQueryTime("insertFeatureVersion", "soiFeatureVersion", t) observeQueryTime("insertFeatureVersion", "soiFeatureVersion", t)
if err != nil { if err != nil {
@ -141,8 +141,9 @@ func (pgSQL *pgSQL) insertFeatureVersion(featureVersion database.FeatureVersion)
return 0, handleError("soiFeatureVersion", err) return 0, handleError("soiFeatureVersion", err)
} }
if newOrExisting == "exi" { if !created {
// That featureVersion already exists, return its id. // The featureVersion already existed, no need to link it to
// vulnerabilities.
tx.Commit() tx.Commit()
if pgSQL.cache != nil { if pgSQL.cache != nil {

View File

@ -63,9 +63,9 @@ const (
WHERE NOT EXISTS (SELECT id FROM FeatureVersion WHERE feature_id = $1 AND version = $2) WHERE NOT EXISTS (SELECT id FROM FeatureVersion WHERE feature_id = $1 AND version = $2)
RETURNING id RETURNING id
) )
SELECT 'exi', id FROM FeatureVersion WHERE feature_id = $1 AND version = $2 SELECT false, id FROM FeatureVersion WHERE feature_id = $1 AND version = $2
UNION UNION
SELECT 'new', id FROM new_featureversion` SELECT true, id FROM new_featureversion`
searchVulnerabilityFixedInFeature = ` searchVulnerabilityFixedInFeature = `
SELECT id, vulnerability_id, version FROM Vulnerability_FixedIn_Feature SELECT id, vulnerability_id, version FROM Vulnerability_FixedIn_Feature
@ -160,10 +160,16 @@ const (
VALUES($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP) VALUES($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP)
RETURNING id` RETURNING id`
insertVulnerabilityFixedInFeature = ` soiVulnerabilityFixedInFeature = `
WITH new_fixedinfeature AS (
INSERT INTO Vulnerability_FixedIn_Feature(vulnerability_id, feature_id, version) INSERT INTO Vulnerability_FixedIn_Feature(vulnerability_id, feature_id, version)
VALUES($1, $2, $3) SELECT CAST($1 AS INTEGER), CAST($2 AS INTEGER), CAST($3 AS VARCHAR)
RETURNING id` WHERE NOT EXISTS (SELECT id FROM Vulnerability_FixedIn_Feature WHERE vulnerability_id = $1 AND feature_id = $2)
RETURNING id
)
SELECT false, id FROM Vulnerability_FixedIn_Feature WHERE vulnerability_id = $1 AND feature_id = $2
UNION
SELECT true, id FROM new_fixedinfeature`
searchFeatureVersionByFeature = `SELECT id, version FROM FeatureVersion WHERE feature_id = $1` searchFeatureVersionByFeature = `SELECT id, version FROM FeatureVersion WHERE feature_id = $1`

View File

@ -433,18 +433,25 @@ func (pgSQL *pgSQL) insertVulnerabilityFixedInFeatureVersions(tx *sql.Tx, vulner
for _, fv := range fixedIn { for _, fv := range fixedIn {
var fixedInID int var fixedInID int
var created bool
// Insert Vulnerability_FixedIn_Feature. // Find or create entry in Vulnerability_FixedIn_Feature.
err = tx.QueryRow( err = tx.QueryRow(
insertVulnerabilityFixedInFeature, soiVulnerabilityFixedInFeature,
vulnerabilityID, fv.Feature.ID, vulnerabilityID, fv.Feature.ID,
&fv.Version, &fv.Version,
).Scan(&fixedInID) ).Scan(&created, &fixedInID)
if err != nil { if err != nil {
return handleError("insertVulnerabilityFixedInFeature", err) return handleError("insertVulnerabilityFixedInFeature", err)
} }
if !created {
// The relationship between the feature and the vulnerability already
// existed, no need to update Vulnerability_Affects_FeatureVersion.
continue
}
// Insert Vulnerability_Affects_FeatureVersion. // Insert Vulnerability_Affects_FeatureVersion.
err = linkVulnerabilityToFeatureVersions(tx, fixedInID, vulnerabilityID, fv.Feature.ID, fv.Version) err = linkVulnerabilityToFeatureVersions(tx, fixedInID, vulnerabilityID, fv.Feature.ID, fv.Version)
if err != nil { if err != nil {

View File

@ -225,25 +225,24 @@ func TestInsertVulnerability(t *testing.T) {
v1.Description = "TestInsertVulnerabilityLink2" v1.Description = "TestInsertVulnerabilityLink2"
v1.Link = "TestInsertVulnerabilityLink2" v1.Link = "TestInsertVulnerabilityLink2"
v1.Severity = types.High v1.Severity = types.High
// Update f3 in f4, add fixed in f5, add fixed in f6 which already exists, removes fixed in f7 by // Update f3 in f4, add fixed in f5, add fixed in f6 which already exists,
// adding f8 which is f7 but with MinVersion. // removes fixed in f7 by adding f8 which is f7 but with MinVersion, and
v1.FixedIn = []database.FeatureVersion{f4, f5, f6, f8} // add fixed by f5 a second time (duplicated).
v1.FixedIn = []database.FeatureVersion{f4, f5, f6, f8, f5}
err = datastore.InsertVulnerabilities([]database.Vulnerability{v1}, true) err = datastore.InsertVulnerabilities([]database.Vulnerability{v1}, true)
if assert.Nil(t, err) { if assert.Nil(t, err) {
v1f, err := datastore.FindVulnerability(n1.Name, v1.Name) v1f, err := datastore.FindVulnerability(n1.Name, v1.Name)
if assert.Nil(t, err) { if assert.Nil(t, err) {
// Remove f8 from the struct for comparison as it was just here to cancel f7.
// Remove one of the f5 too as it was twice in the struct but the database
// implementation should have dedup'd it.
v1.FixedIn = v1.FixedIn[:len(v1.FixedIn)-2]
// We already had f1 before the update. // We already had f1 before the update.
// Add it to the struct for comparison. // Add it to the struct for comparison.
v1.FixedIn = append(v1.FixedIn, f1) v1.FixedIn = append(v1.FixedIn, f1)
// Removes f8 from the struct for comparison as it was just here to cancel f7.
for i := 0; i < len(v1.FixedIn); i++ {
if v1.FixedIn[i].Feature.Name == f8.Feature.Name {
v1.FixedIn = append(v1.FixedIn[:i], v1.FixedIn[i+1:]...)
}
}
equalsVuln(t, &v1, &v1f) equalsVuln(t, &v1, &v1f)
} }
} }