From 6e90b57a442424876b1325b9209f79c8a885a479 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 4 Jul 2017 11:27:47 +0300 Subject: Make use of foreign package objects in build-related functionality --- libbrep/build-extra.sql | 15 +++++++++-- libbrep/build-package.hxx | 69 ++++++++++++++++++++++++++++++++++++++++------- libbrep/build.hxx | 59 +++++++++++++++++++++++++++------------- libbrep/common.hxx | 29 ++++++++++++++++++++ libbrep/package.hxx | 44 ++++++------------------------ 5 files changed, 151 insertions(+), 65 deletions(-) (limited to 'libbrep') diff --git a/libbrep/build-extra.sql b/libbrep/build-extra.sql index 31736c8..6a222a7 100644 --- a/libbrep/build-extra.sql +++ b/libbrep/build-extra.sql @@ -3,11 +3,22 @@ -- file for details. -- --- The foreign table for build_package object. +DROP FOREIGN TABLE IF EXISTS build_package; + +DROP FOREIGN TABLE IF EXISTS build_repository; + +-- The foreign table for build_repository object. -- -- -DROP FOREIGN TABLE IF EXISTS build_package; +CREATE FOREIGN TABLE build_repository ( + name TEXT NOT NULL, + location TEXT NOT NULL, + certificate_fingerprint TEXT NULL) +SERVER package_server OPTIONS (table_name 'repository'); +-- The foreign table for build_package object. +-- +-- CREATE FOREIGN TABLE build_package ( name TEXT NOT NULL, version_epoch INTEGER NOT NULL, diff --git a/libbrep/build-package.hxx b/libbrep/build-package.hxx index b0688c2..8bc703a 100644 --- a/libbrep/build-package.hxx +++ b/libbrep/build-package.hxx @@ -14,13 +14,39 @@ namespace brep { - // This is a "foreign object" that is mapped to the subset of package object - // using PostgreSQL foreign table mechanism. Note that since we maintain the - // two in sync by hand, we should only a have a minimal subset of "core" - // members (ideally just the primary key) that are unlikly to disappear or - // change. + // These are "foreign objects" that are mapped to subsets of the package + // database objects using the PostgreSQL foreign table mechanism. Note that + // since we maintain the pair in sync by hand, we should only have a minimal + // subset of "core" members (ideally just the primary key) that are unlikly + // to disappear or change. // - // The mapping is established in build-extra.sql. + // The mapping is established in build-extra.sql. We also explicitly mark + // non-primary key foreign-mapped members in the source object. + // + // Foreign object that is mapped to the subset of repository object. + // + #pragma db object table("build_repository") pointer(shared_ptr) readonly + class build_repository + { + public: + string name; // Object id (canonical name). + repository_location location; + optional certificate_fingerprint; + + // Database mapping. + // + #pragma db member(name) id + + #pragma db member(location) \ + set(this.location = std::move (?); \ + assert (this.name == this.location.canonical_name ())) + + private: + friend class odb::access; + build_repository () = default; + }; + + // Foreign object that is mapped to the subset of package object. // #pragma db object table("build_package") pointer(shared_ptr) readonly class build_package @@ -28,7 +54,7 @@ namespace brep public: package_id id; upstream_version version; - optional internal_repository; + lazy_shared_ptr internal_repository; // Database mapping. // @@ -40,8 +66,33 @@ namespace brep build_package () = default; }; - #pragma db view object(build_package) - struct build_package_count + // Packages that can potentially be built (internal non-stub). + // + #pragma db view \ + object(build_package) \ + object(build_repository inner: \ + build_package::internal_repository == build_repository::name && \ + brep::compare_version_ne (build_package::id.version, \ + brep::wildcard_version, \ + false)) + struct buildable_package + { + package_id id; + upstream_version version; + + // Database mapping. + // + #pragma db member(version) set(this.version.init (this.id.version, (?))) + }; + + #pragma db view \ + object(build_package) \ + object(build_repository inner: \ + build_package::internal_repository == build_repository::name && \ + brep::compare_version_ne (build_package::id.version, \ + brep::wildcard_version, \ + false)) + struct buildable_package_count { size_t result; diff --git a/libbrep/build.hxx b/libbrep/build.hxx index 7a231bd..7f0aba6 100644 --- a/libbrep/build.hxx +++ b/libbrep/build.hxx @@ -57,10 +57,36 @@ namespace brep inline bool operator< (const build_id& x, const build_id& y) { - return - x.package < y.package ? true : - y.package < x.package ? false : - x.configuration < y.configuration; + if (x.package != y.package) + return x.package < y.package; + + if (int r = x.configuration.compare (y.configuration)) + return r < 0; + + return compare_version_lt (x.toolchain_version, y.toolchain_version, true); + } + + // These allow comparing objects that have package, configuration and + // toolchain_version data members to build_id values. The idea is that this + // works for both query members of build id types as well as for values of + // the build_id type. + // + template + inline auto + operator== (const T& x, const build_id& y) + -> decltype (x.package == y.package) + { + return x.package == y.package && x.configuration == y.configuration && + compare_version_eq (x.toolchain_version, y.toolchain_version, true); + } + + template + inline auto + operator!= (const T& x, const build_id& y) + -> decltype (x.package == y.package) + { + return x.package != y.package || x.configuration != y.configuration || + compare_version_ne (x.toolchain_version, y.toolchain_version, true); } // build_state @@ -267,26 +293,23 @@ namespace brep // Build of an existing internal package. // - #pragma db view \ - object(build) \ - object(build_package inner: \ - build::id.package.name == build_package::id.name && \ - brep::compare_version_eq (build::id.package.version, \ - build_package::id.version, \ - true) && \ + // Note that ADL can't find the equal operator, so we use the function call + // notation. + // + #pragma db view \ + object(build) \ + object(build_package inner: \ + brep::operator== (build::id.package, build_package::id) && \ build_package::internal_repository.is_not_null ()) struct package_build { shared_ptr build; }; - #pragma db view \ - object(build) \ - object(build_package inner: \ - build::id.package.name == build_package::id.name && \ - brep::compare_version_eq (build::id.package.version, \ - build_package::id.version, \ - true) && \ + #pragma db view \ + object(build) \ + object(build_package inner: \ + brep::operator== (build::id.package, build_package::id) && \ build_package::internal_repository.is_not_null ()) struct package_build_count { diff --git a/libbrep/common.hxx b/libbrep/common.hxx index 6bc5aca..56d6768 100644 --- a/libbrep/common.hxx +++ b/libbrep/common.hxx @@ -201,6 +201,13 @@ namespace brep } }; + // repository_location + // + using bpkg::repository_location; + + #pragma db map type(repository_location) as(string) \ + to((?).string ()) from(brep::repository_location (?)) + // Version comparison operators. // // They allow comparing objects that have epoch, canonical_upstream, @@ -330,6 +337,8 @@ namespace brep + x.revision + "DESC"; } + // Package id comparison operators. + // inline bool operator< (const package_id& x, const package_id& y) { @@ -338,6 +347,26 @@ namespace brep return compare_version_lt (x.version, y.version, true); } + + // They allow comparing objects that have name and version data members. The + // idea is that this works for both query members of package id types (in + // particular in join conditions) as well as for values of package_id type. + // + template + inline auto + operator== (const T1& x, const T2& y) + -> decltype (x.name == y.name && x.version.epoch == y.version.epoch) + { + return x.name == y.name && compare_version_eq (x.version, y.version, true); + } + + template + inline auto + operator!= (const T1& x, const T2& y) + -> decltype (x.name == y.name && x.version.epoch == y.version.epoch) + { + return x.name != y.name || compare_version_ne (x.version, y.version, true); + } } #endif // LIBBREP_COMMON_HXX diff --git a/libbrep/package.hxx b/libbrep/package.hxx index 4693a34..5a159ae 100644 --- a/libbrep/package.hxx +++ b/libbrep/package.hxx @@ -164,18 +164,11 @@ namespace brep #pragma db value(requirement_alternatives) definition - // repository_location - // - using bpkg::repository_location; - - #pragma db map type(repository_location) as(string) \ - to((?).string ()) from(brep::repository_location (?)) - #pragma db value class certificate { public: - string fingerprint; // SHA256 fingerprint. + string fingerprint; // SHA256 fingerprint. Note: foreign-mapped in build. string name; // CN component of Subject. string organization; // O component of Subject. string email; // email: in Subject Alternative Name. @@ -202,8 +195,8 @@ namespace brep explicit repository (repository_location); - string name; // Object id (canonical name). - repository_location location; + string name; // Object id (canonical name). + repository_location location; // Note: foreign-mapped in build. string display_name; // The order in the internal repositories configuration file, starting from @@ -224,7 +217,8 @@ namespace brep // repository_location cache_location; - // Present only for internal signed repositories. + // Present only for internal signed repositories. Note that it is + // foreign-mapped in build. // optional certificate; @@ -342,6 +336,9 @@ namespace brep optional build_email; dependencies_type dependencies; requirements_type requirements; + + // Note that it is foreign-mapped in build. + // lazy_shared_ptr internal_repository; // Path to the package file. Present only for internal packages. @@ -483,31 +480,6 @@ namespace brep { package_id id; }; - - #pragma db view object(package) \ - object(repository: package::internal_repository) - struct package_version - { - package_id id; - upstream_version version; - - // Database mapping. - // - #pragma db member(version) set(this.version.init (this.id.version, (?))) - }; - - #pragma db view object(package) \ - object(repository: package::internal_repository) - struct package_version_count - { - size_t result; - - operator size_t () const {return result;} - - // Database mapping. - // - #pragma db member(result) column("count(" + package::id.name + ")") - }; } #endif // LIBBREP_PACKAGE_HXX -- cgit v1.1