aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-08-13 15:48:25 +0200
committerKaren Arutyunov <karen@codesynthesis.com>2021-08-13 17:23:50 +0300
commit97f312a1b536c92440b04ec3dd743fc2802ab150 (patch)
treec232649f6bfb1f566032ad5c5e6e185b3df7d100
parentd1fa0047be1db658b165514dc429ce494517b39c (diff)
Optimize query_dependents() using prepared queries
-rw-r--r--bpkg/database.hxx1
-rwxr-xr-xbpkg/odb.sh5
-rw-r--r--bpkg/package.cxx45
-rw-r--r--bpkg/package.hxx6
-rw-r--r--bpkg/pkg-build.cxx6
-rw-r--r--bpkg/pkg-drop.cxx2
6 files changed, 56 insertions, 9 deletions
diff --git a/bpkg/database.hxx b/bpkg/database.hxx
index 1961272..c7f059d 100644
--- a/bpkg/database.hxx
+++ b/bpkg/database.hxx
@@ -21,6 +21,7 @@
namespace bpkg
{
using odb::query;
+ using odb::prepared_query;
using odb::result;
using odb::session;
diff --git a/bpkg/odb.sh b/bpkg/odb.sh
index 7f494e1..75c6d2d 100755
--- a/bpkg/odb.sh
+++ b/bpkg/odb.sh
@@ -50,6 +50,7 @@ $odb "${inc[@]}" \
--hxx-prologue '#include <bpkg/pointer-traits.hxx>' \
--hxx-prologue '#include <bpkg/wrapper-traits.hxx>' \
--hxx-prologue '#include <bpkg/value-traits.hxx>' \
- --include-with-brackets --include-prefix bpkg --guard-prefix BPKG \
- --schema main --schema-version-table main.schema_version \
+ --generate-prepared --include-with-brackets --include-prefix bpkg \
+ --guard-prefix BPKG --schema main \
+ --schema-version-table main.schema_version \
--sqlite-override-null package.hxx
diff --git a/bpkg/package.cxx b/bpkg/package.cxx
index 7995c34..8ad178d 100644
--- a/bpkg/package.cxx
+++ b/bpkg/package.cxx
@@ -684,10 +684,49 @@ namespace bpkg
const package_name& dep,
database& dep_db)
{
+ // Prepare and cache this query since it's executed a lot. Note that we
+ // have to cache one per database.
+ //
using query = query<package_dependent>;
+ using prep_query = prepared_query<package_dependent>;
+
+ struct params
+ {
+ string name;
+ string config; // Configuration UUID.
+ string query_name;
+ };
+
+ params* qp;
+ string qn (db.uuid.string () + "-package-dependent-query");
+ prep_query pq (db.lookup_query<package_dependent> (qn.c_str (), qp));
+
+ if (!pq)
+ {
+ unique_ptr<params> p (qp = new params ());
+ p->query_name = move (qn);
+
+ query q ("prerequisite = " + query::_ref (p->name) + "AND" +
+ "configuration = " + query::_ref (p->config));
- return db.query<package_dependent> (
- "prerequisite = " + query::_val (dep.string ()) + "AND" +
- "configuration = " + query::_val (dep_db.uuid.string ()));
+ pq = db.prepare_query<package_dependent> (p->query_name.c_str (), q);
+ db.cache_query (pq, move (p));
+ }
+
+ qp->name = dep.string ();
+ qp->config = dep_db.uuid.string ();
+
+ return pq.execute ();
+ }
+
+ vector<package_dependent>
+ query_dependents_cache (database& db,
+ const package_name& dep,
+ database& dep_db)
+ {
+ vector<package_dependent> r;
+ for (package_dependent& pd: query_dependents (db, dep, dep_db))
+ r.push_back (move (pd));
+ return r;
}
}
diff --git a/bpkg/package.hxx b/bpkg/package.hxx
index a0e809a..1a62cd9 100644
--- a/bpkg/package.hxx
+++ b/bpkg/package.hxx
@@ -1314,6 +1314,12 @@ namespace bpkg
const package_name& dependency,
database& dependency_db);
+ // As above but cache the result in a vector. This version should be used if
+ // query_dependents*() may be called recursively.
+ //
+ vector<package_dependent>
+ query_dependents_cache (database&, const package_name&, database&);
+
// Database and package name pair.
//
// It is normally used as a key for maps containing data for packages across
diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx
index d8e5cda..1e8e9dd 100644
--- a/bpkg/pkg-build.cxx
+++ b/bpkg/pkg-build.cxx
@@ -1839,7 +1839,7 @@ namespace bpkg
for (database& ddb: pdb.dependent_configs ())
{
- for (auto& pd: query_dependents (ddb, n, pdb))
+ for (auto& pd: query_dependents_cache (ddb, n, pdb))
{
package_name& dn (pd.name);
auto i (map_.find (ddb, dn));
@@ -2938,7 +2938,7 @@ namespace bpkg
for (database& ddb: db.dependent_configs ())
{
- for (auto& pd: query_dependents (ddb, nm, db))
+ for (auto& pd: query_dependents_cache (ddb, nm, db))
{
// Note that we cannot end up with an infinite recursion for
// configured packages due to a dependency cycle (see order() for
@@ -2998,7 +2998,7 @@ namespace bpkg
for (database& ddb: db.dependent_configs ())
{
- for (auto& pd: query_dependents (ddb, sp->name, db))
+ for (auto& pd: query_dependents_cache (ddb, sp->name, db))
{
shared_ptr<selected_package> dsp (
ddb.load<selected_package> (pd.name));
diff --git a/bpkg/pkg-drop.cxx b/bpkg/pkg-drop.cxx
index e060e96..dfae66f 100644
--- a/bpkg/pkg-drop.cxx
+++ b/bpkg/pkg-drop.cxx
@@ -110,7 +110,7 @@ namespace bpkg
{
for (database& ddb: db.dependent_configs ())
{
- for (auto& pd: query_dependents (ddb, p->name, db))
+ for (auto& pd: query_dependents_cache (ddb, p->name, db))
{
const package_name& dn (pd.name);