From 9a93d815641360ed07a3872f46a0cc382903220c Mon Sep 17 00:00:00 2001 From: Martin Nonnenmacher Date: Mon, 20 Jan 2025 19:27:52 +0100 Subject: [PATCH] WIP: Packages Signed-off-by: Martin Nonnenmacher --- .../repositories/analyzerrun/PackagesTable.kt | 133 +++++++++++++++--- 1 file changed, 113 insertions(+), 20 deletions(-) diff --git a/dao/src/main/kotlin/repositories/analyzerrun/PackagesTable.kt b/dao/src/main/kotlin/repositories/analyzerrun/PackagesTable.kt index 3ef0d70a2..f8ad52411 100644 --- a/dao/src/main/kotlin/repositories/analyzerrun/PackagesTable.kt +++ b/dao/src/main/kotlin/repositories/analyzerrun/PackagesTable.kt @@ -19,21 +19,27 @@ package org.eclipse.apoapsis.ortserver.dao.repositories.analyzerrun -import org.eclipse.apoapsis.ortserver.dao.mapAndCompare import org.eclipse.apoapsis.ortserver.dao.tables.shared.DeclaredLicenseDao +import org.eclipse.apoapsis.ortserver.dao.tables.shared.DeclaredLicensesTable import org.eclipse.apoapsis.ortserver.dao.tables.shared.IdentifierDao import org.eclipse.apoapsis.ortserver.dao.tables.shared.IdentifiersTable import org.eclipse.apoapsis.ortserver.dao.tables.shared.RemoteArtifactDao import org.eclipse.apoapsis.ortserver.dao.tables.shared.RemoteArtifactsTable import org.eclipse.apoapsis.ortserver.dao.tables.shared.VcsInfoDao import org.eclipse.apoapsis.ortserver.dao.tables.shared.VcsInfoTable +import org.eclipse.apoapsis.ortserver.dao.utils.ArrayAggColumnEquals +import org.eclipse.apoapsis.ortserver.dao.utils.ArrayAggNullableColumnEquals +import org.eclipse.apoapsis.ortserver.dao.utils.ArrayAggTwoColumnsEquals import org.eclipse.apoapsis.ortserver.dao.utils.SortableEntityClass import org.eclipse.apoapsis.ortserver.dao.utils.SortableTable import org.eclipse.apoapsis.ortserver.model.runs.Package import org.jetbrains.exposed.dao.LongEntity import org.jetbrains.exposed.dao.id.EntityID -import org.jetbrains.exposed.sql.and +import org.jetbrains.exposed.sql.JoinType +import org.jetbrains.exposed.sql.alias +import org.jetbrains.exposed.sql.andHaving +import org.jetbrains.exposed.sql.andWhere /** * A table to represent all metadata for a software package. @@ -55,25 +61,112 @@ object PackagesTable : SortableTable("packages") { class PackageDao(id: EntityID) : LongEntity(id) { companion object : SortableEntityClass(PackagesTable) { - fun findByPackage(pkg: Package): PackageDao? = + fun findByPackage(pkg: Package): PackageDao? { + val vcsProcessed = VcsInfoTable.alias("vcs_processed_info") + val binaryArtifacts = RemoteArtifactsTable.alias("binary_artifacts") + val sourceArtifacts = RemoteArtifactsTable.alias("source_artifacts") + val query = PackagesTable + .leftJoin(IdentifiersTable) + .join(VcsInfoTable, JoinType.LEFT, onColumn = PackagesTable.vcsId, otherColumn = VcsInfoTable.id) + .join(vcsProcessed, JoinType.LEFT, PackagesTable.vcsProcessedId, vcsProcessed[VcsInfoTable.id]) + .join( + binaryArtifacts, + JoinType.LEFT, + PackagesTable.binaryArtifactId, + binaryArtifacts[RemoteArtifactsTable.id] + ) + .join( + sourceArtifacts, + JoinType.LEFT, + PackagesTable.sourceArtifactId, + sourceArtifacts[RemoteArtifactsTable.id] + ) + .leftJoin(PackagesAuthorsTable) + .leftJoin(AuthorsTable) + .leftJoin(PackagesDeclaredLicensesTable) + .leftJoin(DeclaredLicensesTable) + .leftJoin(ProcessedDeclaredLicensesTable) + .leftJoin(ProcessedDeclaredLicensesMappedDeclaredLicensesTable) + .leftJoin(MappedDeclaredLicensesTable) + .leftJoin(ProcessedDeclaredLicensesUnmappedDeclaredLicensesTable) + .leftJoin(UnmappedDeclaredLicensesTable) + .select(PackagesTable.id) + .where { PackagesTable.purl eq pkg.purl } + .andWhere { PackagesTable.cpe eq pkg.cpe } + .andWhere { PackagesTable.description eq pkg.description } + .andWhere { PackagesTable.homepageUrl eq pkg.homepageUrl } + .andWhere { PackagesTable.isMetadataOnly eq pkg.isMetadataOnly } + .andWhere { PackagesTable.isModified eq pkg.isModified } + .andWhere { IdentifiersTable.type eq pkg.identifier.type } + .andWhere { IdentifiersTable.namespace eq pkg.identifier.namespace } + .andWhere { IdentifiersTable.name eq pkg.identifier.name } + .andWhere { IdentifiersTable.version eq pkg.identifier.version } + .andWhere { VcsInfoTable.type eq pkg.vcs.type.name } + .andWhere { VcsInfoTable.url eq pkg.vcs.url } + .andWhere { VcsInfoTable.revision eq pkg.vcs.revision } + .andWhere { VcsInfoTable.path eq pkg.vcs.path } + .andWhere { vcsProcessed[VcsInfoTable.type] eq pkg.vcsProcessed.type.name } + .andWhere { vcsProcessed[VcsInfoTable.url] eq pkg.vcsProcessed.url } + .andWhere { vcsProcessed[VcsInfoTable.revision] eq pkg.vcsProcessed.revision } + .andWhere { vcsProcessed[VcsInfoTable.path] eq pkg.vcsProcessed.path } + .andWhere { binaryArtifacts[RemoteArtifactsTable.url] eq pkg.binaryArtifact.url } + .andWhere { binaryArtifacts[RemoteArtifactsTable.hashValue] eq pkg.binaryArtifact.hashValue } + .andWhere { binaryArtifacts[RemoteArtifactsTable.hashAlgorithm] eq pkg.binaryArtifact.hashAlgorithm } + .andWhere { sourceArtifacts[RemoteArtifactsTable.url] eq pkg.sourceArtifact.url } + .andWhere { sourceArtifacts[RemoteArtifactsTable.hashValue] eq pkg.sourceArtifact.hashValue } + .andWhere { sourceArtifacts[RemoteArtifactsTable.hashAlgorithm] eq pkg.sourceArtifact.hashAlgorithm } + .groupBy( + PackagesTable.id, + IdentifiersTable.id, + VcsInfoTable.id, + vcsProcessed[VcsInfoTable.id], + binaryArtifacts[RemoteArtifactsTable.id], + sourceArtifacts[RemoteArtifactsTable.id] + ) + .having { ArrayAggColumnEquals(AuthorsTable.name, pkg.authors) } + .andHaving { ArrayAggColumnEquals(DeclaredLicensesTable.name, pkg.declaredLicenses) } + .andHaving { + ArrayAggNullableColumnEquals( + ProcessedDeclaredLicensesTable.spdxExpression, + setOf(pkg.processedDeclaredLicense.spdxExpression.toString()) + ) + } + .andHaving { + ArrayAggColumnEquals( + UnmappedDeclaredLicensesTable.unmappedLicense, + pkg.processedDeclaredLicense.unmappedLicenses + ) + } + .andHaving { + ArrayAggTwoColumnsEquals( + MappedDeclaredLicensesTable.declaredLicense, + MappedDeclaredLicensesTable.mappedLicense, + pkg.processedDeclaredLicense.mappedLicenses + ) + } + + val id = query.firstOrNull()?.let { it[PackagesTable.id] } ?: return null + + return PackageDao[id] + } // TODO: Implement a more efficient way to check if an identical package already exists. - find { - PackagesTable.purl eq pkg.purl and - (PackagesTable.cpe eq pkg.cpe) and - (PackagesTable.description eq pkg.description) and - (PackagesTable.homepageUrl eq pkg.homepageUrl) and - (PackagesTable.isMetadataOnly eq pkg.isMetadataOnly) and - (PackagesTable.isModified eq pkg.isModified) - }.firstOrNull { - it.identifier.mapToModel() == pkg.identifier && - mapAndCompare(it.authors, pkg.authors, AuthorDao::name) && - mapAndCompare(it.declaredLicenses, pkg.declaredLicenses, DeclaredLicenseDao::name) && - it.processedDeclaredLicense.mapToModel() == pkg.processedDeclaredLicense && - it.vcs.mapToModel() == pkg.vcs && - it.vcsProcessed.mapToModel() == pkg.vcsProcessed && - it.binaryArtifact.mapToModel() == pkg.binaryArtifact && - it.sourceArtifact.mapToModel() == pkg.sourceArtifact - } +// find { +// PackagesTable.purl eq pkg.purl and +// (PackagesTable.cpe eq pkg.cpe) and +// (PackagesTable.description eq pkg.description) and +// (PackagesTable.homepageUrl eq pkg.homepageUrl) and +// (PackagesTable.isMetadataOnly eq pkg.isMetadataOnly) and +// (PackagesTable.isModified eq pkg.isModified) +// }.firstOrNull { +// it.identifier.mapToModel() == pkg.identifier && +// mapAndCompare(it.authors, pkg.authors, AuthorDao::name) && +// mapAndCompare(it.declaredLicenses, pkg.declaredLicenses, DeclaredLicenseDao::name) && +// it.processedDeclaredLicense.mapToModel() == pkg.processedDeclaredLicense && +// it.vcs.mapToModel() == pkg.vcs && +// it.vcsProcessed.mapToModel() == pkg.vcsProcessed && +// it.binaryArtifact.mapToModel() == pkg.binaryArtifact && +// it.sourceArtifact.mapToModel() == pkg.sourceArtifact +// } } var identifier by IdentifierDao referencedOn PackagesTable.identifierId