Struct Loader

Source
pub struct Loader<'a> { /* private fields */ }
Expand description

Perform a streaming load of only relevant database tables.

§Example

This example loads just the version_downloads.csv table, in which each row is the download count for a single version of a single crate on a single day. We do not store the rows individually in memory but instead stream from the csv to accumulate just a total count per day across all crates, which requires far less memory.

use chrono::Utc;
use db_dump::Date;
use std::collections::BTreeMap as Map;

fn main() -> db_dump::Result<()> {
    let mut downloads = Map::<Date<Utc>, u64>::new();
    db_dump::Loader::new()
        .version_downloads(|row| {
            *downloads.entry(row.date).or_default() += row.downloads;
        })
        .load("./db-dump.tar.gz")?;

    for (date, count) in downloads {
        println!("{},{}", date, count);
    }

    Ok(())
}

Implementations§

Source§

impl<'a> Loader<'a>

Source

pub fn new() -> Self

Examples found in repository?
examples/total-downloads.rs (line 12)
10fn main() -> db_dump::Result<()> {
11    let mut downloads = Map::<Date<Utc>, u64>::new();
12    db_dump::Loader::new()
13        .version_downloads(|row| {
14            *downloads.entry(row.date).or_default() += row.downloads;
15        })
16        .load("./db-dump.tar.gz")?;
17
18    for (date, count) in downloads {
19        println!("{},{}", date, count);
20    }
21
22    Ok(())
23}
More examples
Hide additional examples
examples/crate-downloads.rs (line 15)
11fn main() -> db_dump::Result<()> {
12    let mut crate_id = None;
13    let mut versions = Vec::new();
14    let mut version_downloads = Vec::new();
15    db_dump::Loader::new()
16        .crates(|row| {
17            if row.name == CRATE {
18                crate_id = Some(row.id);
19            }
20        })
21        .versions(|row| versions.push(row))
22        .version_downloads(|row| version_downloads.push(row))
23        .load("./db-dump.tar.gz")?;
24
25    // Crate id of the crate we care about.
26    let crate_id = crate_id.expect("no such crate");
27
28    // Set of all version ids corresponding to that crate.
29    let mut version_ids = Set::new();
30    for version in versions {
31        if version.crate_id == crate_id {
32            version_ids.insert(version.id);
33        }
34    }
35
36    // Add up downloads across all version of the crate by day.
37    let mut downloads = Map::<Date<Utc>, u64>::new();
38    for stat in version_downloads {
39        if version_ids.contains(&stat.version_id) {
40            *downloads.entry(stat.date).or_default() += stat.downloads;
41        }
42    }
43
44    for (date, count) in downloads {
45        println!("{},{}", date, count);
46    }
47
48    Ok(())
49}
examples/user-downloads.rs (line 23)
18fn main() -> db_dump::Result<()> {
19    let mut user_id = None;
20    let mut crate_owners = Vec::new();
21    let mut versions = Vec::new();
22    let mut version_downloads = Vec::new();
23    db_dump::Loader::new()
24        .users(|row| {
25            if row.gh_login == USER {
26                user_id = Some(row.id);
27            }
28        })
29        .crate_owners(|row| crate_owners.push(row))
30        .versions(|row| versions.push(row))
31        .version_downloads(|row| version_downloads.push(row))
32        .load("./db-dump.tar.gz")?;
33
34    // User id of the crate author we care about.
35    let user_id = user_id.expect("no such user");
36
37    // Set of crate ids currently owned by that user.
38    let mut their_crates = Set::new();
39    for crate_owner in crate_owners {
40        if crate_owner.owner_id == user_id {
41            their_crates.insert(crate_owner.crate_id);
42        }
43    }
44
45    // Set of version ids of all of those crates.
46    let mut their_versions = Set::new();
47    for version in versions {
48        if their_crates.contains(&version.crate_id) {
49            their_versions.insert(version.id);
50        }
51    }
52
53    // Add up downloads across that user's crates, as well as total downloads of
54    // all crates.
55    let mut downloads = Map::<Date<Utc>, Downloads>::new();
56    for stat in version_downloads {
57        let entry = downloads.entry(stat.date).or_default();
58        entry.all += stat.downloads;
59        if their_versions.contains(&stat.version_id) {
60            entry.theirs += stat.downloads;
61        }
62    }
63
64    // Print user's downloads as a fraction of total crates.io downloads by day.
65    for (date, downloads) in downloads {
66        if downloads.theirs > 0 {
67            println!(
68                "{},{}",
69                date,
70                downloads.theirs as f64 / downloads.all as f64,
71            );
72        }
73    }
74
75    Ok(())
76}
examples/user-dependencies.rs (line 19)
11fn main() -> db_dump::Result<()> {
12    // Map of crate id to the most recently published version of that crate.
13    let mut most_recent = Map::new();
14
15    let mut user_id = None;
16    let mut crates = 0;
17    let mut crate_owners = Vec::new();
18    let mut dependencies = Vec::new();
19    db_dump::Loader::new()
20        .users(|row| {
21            if row.gh_login == USER {
22                user_id = Some(row.id);
23            }
24        })
25        .crates(|_row| crates += 1)
26        .crate_owners(|row| crate_owners.push(row))
27        .dependencies(|row| dependencies.push(row))
28        .versions(|row| match most_recent.entry(row.crate_id) {
29            Entry::Vacant(entry) => {
30                entry.insert(row);
31            }
32            Entry::Occupied(mut entry) => {
33                if row.created_at > entry.get().created_at {
34                    entry.insert(row);
35                }
36            }
37        })
38        .load("./db-dump.tar.gz")?;
39
40    // User id of the crate author we care about.
41    let user_id = user_id.expect("no such user");
42
43    // Set of crate ids currently owned by that user.
44    let mut their_crates = Set::new();
45    for crate_owner in crate_owners {
46        if crate_owner.owner_id == user_id {
47            their_crates.insert(crate_owner.crate_id);
48        }
49    }
50
51    // Set of version ids which are the most recently published of their crate.
52    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54    // Set of version ids which depend directly on at least one crate by the
55    // user.
56    let mut dep_on_them = Set::new();
57    for dep in dependencies {
58        if their_crates.contains(&dep.crate_id) {
59            dep_on_them.insert(dep.version_id);
60        }
61    }
62
63    // Number of crates whose most recent version depends on at least one crate
64    // by the user.
65    let result = dep_on_them.intersection(&most_recent).count();
66
67    println!(
68        "{} / {} = {:.1}%",
69        result,
70        crates,
71        100.0 * result as f64 / crates as f64,
72    );
73
74    Ok(())
75}
examples/top-crates.rs (line 20)
13fn main() -> db_dump::Result<()> {
14    // Map of crate id to the most recently published version of that crate.
15    let mut most_recent = Map::new();
16
17    let mut crates = Set::new();
18    let mut crate_owners = Vec::new();
19    let mut dependencies = Vec::new();
20    db_dump::Loader::new()
21        .crates(|row| {
22            crates.insert(row);
23        })
24        .crate_owners(|row| crate_owners.push(row))
25        .dependencies(|row| dependencies.push(row))
26        .versions(|row| match most_recent.entry(row.crate_id) {
27            Entry::Vacant(entry) => {
28                entry.insert(row);
29            }
30            Entry::Occupied(mut entry) => {
31                if row.created_at > entry.get().created_at {
32                    entry.insert(row);
33                }
34            }
35        })
36        .load("./db-dump.tar.gz")?;
37
38    // Set of version ids which are the most recently published of their crate.
39    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41    // Set of (version id, dependency crate id) pairs to avoid double-counting
42    // cases where a crate has both a normal dependency and dev-dependency or
43    // build-dependency on the same dependency crate.
44    let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46    // Map of crate id to how many other crates' most recent version depends on
47    // that crate.
48    let mut count = Map::<CrateId, usize>::new();
49    for dep in dependencies {
50        if most_recent.contains(&dep.version_id)
51            && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52        {
53            *count.entry(dep.crate_id).or_default() += 1;
54        }
55    }
56
57    // Quickselect and sort the top N crates by reverse dependency count.
58    let mut sort = Vec::from_iter(count);
59    let sort_by_count = |&(_crate, count): &_| Reverse(count);
60    sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61    sort[..N].sort_unstable_by_key(sort_by_count);
62
63    for (id, count) in sort.iter().take(N) {
64        let crate_name = &crates.get(id).unwrap().name;
65        println!("{},{}", crate_name, count);
66    }
67
68    Ok(())
69}
examples/user-dependencies-graph.rs (line 15)
10fn main() -> db_dump::Result<()> {
11    let mut user_id = None;
12    let mut crate_owners = Vec::new();
13    let mut dependencies = Map::new();
14    let mut versions = Vec::new();
15    db_dump::Loader::new()
16        .users(|row| {
17            if row.gh_login == USER {
18                user_id = Some(row.id);
19            }
20        })
21        .crate_owners(|row| crate_owners.push(row))
22        .dependencies(|row| {
23            dependencies
24                .entry(row.version_id)
25                .or_insert_with(Vec::new)
26                .push(row);
27        })
28        .versions(|row| {
29            if !row.yanked {
30                versions.push(row);
31            }
32        })
33        .load("./db-dump.tar.gz")?;
34
35    // User id of the crate author we care about.
36    let user_id = user_id.expect("no such user");
37
38    // Set of crate ids currently owned by that user.
39    let mut their_crates = Set::new();
40    for crate_owner in crate_owners {
41        if crate_owner.owner_id == user_id {
42            their_crates.insert(crate_owner.crate_id);
43        }
44    }
45
46    let mut total_deps = 0usize;
47    let mut their_deps = 0usize;
48    let mut last_printed_ratio = 0.0..=0.0;
49    let mut latest_version = Map::new();
50
51    versions.sort_by_key(|v| v.created_at);
52
53    for version in versions {
54        let no_deps = Vec::new();
55        if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56            for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57                total_deps -= 1;
58                their_deps -= their_crates.contains(&dep.crate_id) as usize;
59            }
60        }
61        for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62            total_deps += 1;
63            their_deps += their_crates.contains(&dep.crate_id) as usize;
64        }
65        if total_deps != 0 {
66            let ratio = their_deps as f64 / total_deps as f64;
67            if !last_printed_ratio.contains(&ratio) {
68                println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69                last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70            }
71        }
72    }
73
74    eprintln!(
75        "{} / {} ({:.02}%)",
76        their_deps,
77        total_deps,
78        (their_deps as f64 / total_deps as f64) * 100.0,
79    );
80    Ok(())
81}
Source

pub fn categories(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Source

pub fn crate_downloads(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Source

pub fn crate_owners(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Examples found in repository?
examples/user-downloads.rs (line 29)
18fn main() -> db_dump::Result<()> {
19    let mut user_id = None;
20    let mut crate_owners = Vec::new();
21    let mut versions = Vec::new();
22    let mut version_downloads = Vec::new();
23    db_dump::Loader::new()
24        .users(|row| {
25            if row.gh_login == USER {
26                user_id = Some(row.id);
27            }
28        })
29        .crate_owners(|row| crate_owners.push(row))
30        .versions(|row| versions.push(row))
31        .version_downloads(|row| version_downloads.push(row))
32        .load("./db-dump.tar.gz")?;
33
34    // User id of the crate author we care about.
35    let user_id = user_id.expect("no such user");
36
37    // Set of crate ids currently owned by that user.
38    let mut their_crates = Set::new();
39    for crate_owner in crate_owners {
40        if crate_owner.owner_id == user_id {
41            their_crates.insert(crate_owner.crate_id);
42        }
43    }
44
45    // Set of version ids of all of those crates.
46    let mut their_versions = Set::new();
47    for version in versions {
48        if their_crates.contains(&version.crate_id) {
49            their_versions.insert(version.id);
50        }
51    }
52
53    // Add up downloads across that user's crates, as well as total downloads of
54    // all crates.
55    let mut downloads = Map::<Date<Utc>, Downloads>::new();
56    for stat in version_downloads {
57        let entry = downloads.entry(stat.date).or_default();
58        entry.all += stat.downloads;
59        if their_versions.contains(&stat.version_id) {
60            entry.theirs += stat.downloads;
61        }
62    }
63
64    // Print user's downloads as a fraction of total crates.io downloads by day.
65    for (date, downloads) in downloads {
66        if downloads.theirs > 0 {
67            println!(
68                "{},{}",
69                date,
70                downloads.theirs as f64 / downloads.all as f64,
71            );
72        }
73    }
74
75    Ok(())
76}
More examples
Hide additional examples
examples/user-dependencies.rs (line 26)
11fn main() -> db_dump::Result<()> {
12    // Map of crate id to the most recently published version of that crate.
13    let mut most_recent = Map::new();
14
15    let mut user_id = None;
16    let mut crates = 0;
17    let mut crate_owners = Vec::new();
18    let mut dependencies = Vec::new();
19    db_dump::Loader::new()
20        .users(|row| {
21            if row.gh_login == USER {
22                user_id = Some(row.id);
23            }
24        })
25        .crates(|_row| crates += 1)
26        .crate_owners(|row| crate_owners.push(row))
27        .dependencies(|row| dependencies.push(row))
28        .versions(|row| match most_recent.entry(row.crate_id) {
29            Entry::Vacant(entry) => {
30                entry.insert(row);
31            }
32            Entry::Occupied(mut entry) => {
33                if row.created_at > entry.get().created_at {
34                    entry.insert(row);
35                }
36            }
37        })
38        .load("./db-dump.tar.gz")?;
39
40    // User id of the crate author we care about.
41    let user_id = user_id.expect("no such user");
42
43    // Set of crate ids currently owned by that user.
44    let mut their_crates = Set::new();
45    for crate_owner in crate_owners {
46        if crate_owner.owner_id == user_id {
47            their_crates.insert(crate_owner.crate_id);
48        }
49    }
50
51    // Set of version ids which are the most recently published of their crate.
52    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54    // Set of version ids which depend directly on at least one crate by the
55    // user.
56    let mut dep_on_them = Set::new();
57    for dep in dependencies {
58        if their_crates.contains(&dep.crate_id) {
59            dep_on_them.insert(dep.version_id);
60        }
61    }
62
63    // Number of crates whose most recent version depends on at least one crate
64    // by the user.
65    let result = dep_on_them.intersection(&most_recent).count();
66
67    println!(
68        "{} / {} = {:.1}%",
69        result,
70        crates,
71        100.0 * result as f64 / crates as f64,
72    );
73
74    Ok(())
75}
examples/top-crates.rs (line 24)
13fn main() -> db_dump::Result<()> {
14    // Map of crate id to the most recently published version of that crate.
15    let mut most_recent = Map::new();
16
17    let mut crates = Set::new();
18    let mut crate_owners = Vec::new();
19    let mut dependencies = Vec::new();
20    db_dump::Loader::new()
21        .crates(|row| {
22            crates.insert(row);
23        })
24        .crate_owners(|row| crate_owners.push(row))
25        .dependencies(|row| dependencies.push(row))
26        .versions(|row| match most_recent.entry(row.crate_id) {
27            Entry::Vacant(entry) => {
28                entry.insert(row);
29            }
30            Entry::Occupied(mut entry) => {
31                if row.created_at > entry.get().created_at {
32                    entry.insert(row);
33                }
34            }
35        })
36        .load("./db-dump.tar.gz")?;
37
38    // Set of version ids which are the most recently published of their crate.
39    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41    // Set of (version id, dependency crate id) pairs to avoid double-counting
42    // cases where a crate has both a normal dependency and dev-dependency or
43    // build-dependency on the same dependency crate.
44    let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46    // Map of crate id to how many other crates' most recent version depends on
47    // that crate.
48    let mut count = Map::<CrateId, usize>::new();
49    for dep in dependencies {
50        if most_recent.contains(&dep.version_id)
51            && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52        {
53            *count.entry(dep.crate_id).or_default() += 1;
54        }
55    }
56
57    // Quickselect and sort the top N crates by reverse dependency count.
58    let mut sort = Vec::from_iter(count);
59    let sort_by_count = |&(_crate, count): &_| Reverse(count);
60    sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61    sort[..N].sort_unstable_by_key(sort_by_count);
62
63    for (id, count) in sort.iter().take(N) {
64        let crate_name = &crates.get(id).unwrap().name;
65        println!("{},{}", crate_name, count);
66    }
67
68    Ok(())
69}
examples/user-dependencies-graph.rs (line 21)
10fn main() -> db_dump::Result<()> {
11    let mut user_id = None;
12    let mut crate_owners = Vec::new();
13    let mut dependencies = Map::new();
14    let mut versions = Vec::new();
15    db_dump::Loader::new()
16        .users(|row| {
17            if row.gh_login == USER {
18                user_id = Some(row.id);
19            }
20        })
21        .crate_owners(|row| crate_owners.push(row))
22        .dependencies(|row| {
23            dependencies
24                .entry(row.version_id)
25                .or_insert_with(Vec::new)
26                .push(row);
27        })
28        .versions(|row| {
29            if !row.yanked {
30                versions.push(row);
31            }
32        })
33        .load("./db-dump.tar.gz")?;
34
35    // User id of the crate author we care about.
36    let user_id = user_id.expect("no such user");
37
38    // Set of crate ids currently owned by that user.
39    let mut their_crates = Set::new();
40    for crate_owner in crate_owners {
41        if crate_owner.owner_id == user_id {
42            their_crates.insert(crate_owner.crate_id);
43        }
44    }
45
46    let mut total_deps = 0usize;
47    let mut their_deps = 0usize;
48    let mut last_printed_ratio = 0.0..=0.0;
49    let mut latest_version = Map::new();
50
51    versions.sort_by_key(|v| v.created_at);
52
53    for version in versions {
54        let no_deps = Vec::new();
55        if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56            for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57                total_deps -= 1;
58                their_deps -= their_crates.contains(&dep.crate_id) as usize;
59            }
60        }
61        for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62            total_deps += 1;
63            their_deps += their_crates.contains(&dep.crate_id) as usize;
64        }
65        if total_deps != 0 {
66            let ratio = their_deps as f64 / total_deps as f64;
67            if !last_printed_ratio.contains(&ratio) {
68                println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69                last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70            }
71        }
72    }
73
74    eprintln!(
75        "{} / {} ({:.02}%)",
76        their_deps,
77        total_deps,
78        (their_deps as f64 / total_deps as f64) * 100.0,
79    );
80    Ok(())
81}
Source

pub fn crates(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Examples found in repository?
examples/crate-downloads.rs (lines 16-20)
11fn main() -> db_dump::Result<()> {
12    let mut crate_id = None;
13    let mut versions = Vec::new();
14    let mut version_downloads = Vec::new();
15    db_dump::Loader::new()
16        .crates(|row| {
17            if row.name == CRATE {
18                crate_id = Some(row.id);
19            }
20        })
21        .versions(|row| versions.push(row))
22        .version_downloads(|row| version_downloads.push(row))
23        .load("./db-dump.tar.gz")?;
24
25    // Crate id of the crate we care about.
26    let crate_id = crate_id.expect("no such crate");
27
28    // Set of all version ids corresponding to that crate.
29    let mut version_ids = Set::new();
30    for version in versions {
31        if version.crate_id == crate_id {
32            version_ids.insert(version.id);
33        }
34    }
35
36    // Add up downloads across all version of the crate by day.
37    let mut downloads = Map::<Date<Utc>, u64>::new();
38    for stat in version_downloads {
39        if version_ids.contains(&stat.version_id) {
40            *downloads.entry(stat.date).or_default() += stat.downloads;
41        }
42    }
43
44    for (date, count) in downloads {
45        println!("{},{}", date, count);
46    }
47
48    Ok(())
49}
More examples
Hide additional examples
examples/user-dependencies.rs (line 25)
11fn main() -> db_dump::Result<()> {
12    // Map of crate id to the most recently published version of that crate.
13    let mut most_recent = Map::new();
14
15    let mut user_id = None;
16    let mut crates = 0;
17    let mut crate_owners = Vec::new();
18    let mut dependencies = Vec::new();
19    db_dump::Loader::new()
20        .users(|row| {
21            if row.gh_login == USER {
22                user_id = Some(row.id);
23            }
24        })
25        .crates(|_row| crates += 1)
26        .crate_owners(|row| crate_owners.push(row))
27        .dependencies(|row| dependencies.push(row))
28        .versions(|row| match most_recent.entry(row.crate_id) {
29            Entry::Vacant(entry) => {
30                entry.insert(row);
31            }
32            Entry::Occupied(mut entry) => {
33                if row.created_at > entry.get().created_at {
34                    entry.insert(row);
35                }
36            }
37        })
38        .load("./db-dump.tar.gz")?;
39
40    // User id of the crate author we care about.
41    let user_id = user_id.expect("no such user");
42
43    // Set of crate ids currently owned by that user.
44    let mut their_crates = Set::new();
45    for crate_owner in crate_owners {
46        if crate_owner.owner_id == user_id {
47            their_crates.insert(crate_owner.crate_id);
48        }
49    }
50
51    // Set of version ids which are the most recently published of their crate.
52    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54    // Set of version ids which depend directly on at least one crate by the
55    // user.
56    let mut dep_on_them = Set::new();
57    for dep in dependencies {
58        if their_crates.contains(&dep.crate_id) {
59            dep_on_them.insert(dep.version_id);
60        }
61    }
62
63    // Number of crates whose most recent version depends on at least one crate
64    // by the user.
65    let result = dep_on_them.intersection(&most_recent).count();
66
67    println!(
68        "{} / {} = {:.1}%",
69        result,
70        crates,
71        100.0 * result as f64 / crates as f64,
72    );
73
74    Ok(())
75}
examples/top-crates.rs (lines 21-23)
13fn main() -> db_dump::Result<()> {
14    // Map of crate id to the most recently published version of that crate.
15    let mut most_recent = Map::new();
16
17    let mut crates = Set::new();
18    let mut crate_owners = Vec::new();
19    let mut dependencies = Vec::new();
20    db_dump::Loader::new()
21        .crates(|row| {
22            crates.insert(row);
23        })
24        .crate_owners(|row| crate_owners.push(row))
25        .dependencies(|row| dependencies.push(row))
26        .versions(|row| match most_recent.entry(row.crate_id) {
27            Entry::Vacant(entry) => {
28                entry.insert(row);
29            }
30            Entry::Occupied(mut entry) => {
31                if row.created_at > entry.get().created_at {
32                    entry.insert(row);
33                }
34            }
35        })
36        .load("./db-dump.tar.gz")?;
37
38    // Set of version ids which are the most recently published of their crate.
39    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41    // Set of (version id, dependency crate id) pairs to avoid double-counting
42    // cases where a crate has both a normal dependency and dev-dependency or
43    // build-dependency on the same dependency crate.
44    let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46    // Map of crate id to how many other crates' most recent version depends on
47    // that crate.
48    let mut count = Map::<CrateId, usize>::new();
49    for dep in dependencies {
50        if most_recent.contains(&dep.version_id)
51            && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52        {
53            *count.entry(dep.crate_id).or_default() += 1;
54        }
55    }
56
57    // Quickselect and sort the top N crates by reverse dependency count.
58    let mut sort = Vec::from_iter(count);
59    let sort_by_count = |&(_crate, count): &_| Reverse(count);
60    sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61    sort[..N].sort_unstable_by_key(sort_by_count);
62
63    for (id, count) in sort.iter().take(N) {
64        let crate_name = &crates.get(id).unwrap().name;
65        println!("{},{}", crate_name, count);
66    }
67
68    Ok(())
69}
examples/industry-coefficient.rs (lines 25-27)
20fn main() -> db_dump::Result<()> {
21    let mut crates: Map<CrateId, String> = Map::new();
22    let mut versions: Map<VersionId, CrateId> = Map::new();
23    let mut version_downloads = Vec::new();
24    db_dump::Loader::new()
25        .crates(|row| {
26            crates.insert(row.id, row.name);
27        })
28        .versions(|row| {
29            versions.insert(row.id, row.crate_id);
30        })
31        .version_downloads(|row| version_downloads.push(row))
32        .load("./db-dump.tar.gz")?;
33
34    let max_date = version_downloads.iter().map(|row| row.date).max().unwrap();
35    let start_date = max_date - TimeDelta::try_weeks(6).unwrap();
36
37    // Add up downloads by crate by date
38    let mut downloads: Map<CrateId, Downloads> = Map::new();
39    for row in version_downloads {
40        // Deliberately cut out the largest date in the db-dump, because the
41        // data is partial.
42        if row.date >= start_date && row.date < max_date {
43            let crate_id = versions[&row.version_id];
44            let downloads = downloads.entry(crate_id).or_insert_with(Downloads::default);
45            match row.date.weekday() {
46                Weekday::Tue | Weekday::Wed | Weekday::Thu => downloads.weekday += row.downloads,
47                Weekday::Sat | Weekday::Sun => downloads.weekend += row.downloads,
48                // Disregard these to reduce some boundary effect from
49                // downloaders not being perfectly aligned with UTC.
50                Weekday::Mon | Weekday::Fri => {}
51            }
52        }
53    }
54
55    let mut downloads_vec = Vec::new();
56    let mut total = Downloads::default();
57    for (crate_id, downloads) in downloads {
58        total.weekday += downloads.weekday;
59        total.weekend += downloads.weekend;
60        let crate_name = &crates[&crate_id];
61        if downloads.weekend > 0
62            && (downloads.weekday + downloads.weekend >= DOWNLOADS_CUTOFF || crate_name == "cxx")
63        {
64            let coefficient = downloads.weekday as f64 / downloads.weekend as f64;
65            downloads_vec.push((crate_name, coefficient));
66        }
67    }
68
69    let mean = total.weekday as f64 / total.weekend as f64;
70    downloads_vec.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
71
72    for (crate_name, coefficient) in downloads_vec {
73        println!("{:>36}  {:+.4}", crate_name, coefficient - mean);
74    }
75
76    Ok(())
77}
Source

pub fn crates_categories(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Source

pub fn crates_keywords(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Source

pub fn default_versions(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Source

pub fn dependencies(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Examples found in repository?
examples/user-dependencies.rs (line 27)
11fn main() -> db_dump::Result<()> {
12    // Map of crate id to the most recently published version of that crate.
13    let mut most_recent = Map::new();
14
15    let mut user_id = None;
16    let mut crates = 0;
17    let mut crate_owners = Vec::new();
18    let mut dependencies = Vec::new();
19    db_dump::Loader::new()
20        .users(|row| {
21            if row.gh_login == USER {
22                user_id = Some(row.id);
23            }
24        })
25        .crates(|_row| crates += 1)
26        .crate_owners(|row| crate_owners.push(row))
27        .dependencies(|row| dependencies.push(row))
28        .versions(|row| match most_recent.entry(row.crate_id) {
29            Entry::Vacant(entry) => {
30                entry.insert(row);
31            }
32            Entry::Occupied(mut entry) => {
33                if row.created_at > entry.get().created_at {
34                    entry.insert(row);
35                }
36            }
37        })
38        .load("./db-dump.tar.gz")?;
39
40    // User id of the crate author we care about.
41    let user_id = user_id.expect("no such user");
42
43    // Set of crate ids currently owned by that user.
44    let mut their_crates = Set::new();
45    for crate_owner in crate_owners {
46        if crate_owner.owner_id == user_id {
47            their_crates.insert(crate_owner.crate_id);
48        }
49    }
50
51    // Set of version ids which are the most recently published of their crate.
52    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54    // Set of version ids which depend directly on at least one crate by the
55    // user.
56    let mut dep_on_them = Set::new();
57    for dep in dependencies {
58        if their_crates.contains(&dep.crate_id) {
59            dep_on_them.insert(dep.version_id);
60        }
61    }
62
63    // Number of crates whose most recent version depends on at least one crate
64    // by the user.
65    let result = dep_on_them.intersection(&most_recent).count();
66
67    println!(
68        "{} / {} = {:.1}%",
69        result,
70        crates,
71        100.0 * result as f64 / crates as f64,
72    );
73
74    Ok(())
75}
More examples
Hide additional examples
examples/top-crates.rs (line 25)
13fn main() -> db_dump::Result<()> {
14    // Map of crate id to the most recently published version of that crate.
15    let mut most_recent = Map::new();
16
17    let mut crates = Set::new();
18    let mut crate_owners = Vec::new();
19    let mut dependencies = Vec::new();
20    db_dump::Loader::new()
21        .crates(|row| {
22            crates.insert(row);
23        })
24        .crate_owners(|row| crate_owners.push(row))
25        .dependencies(|row| dependencies.push(row))
26        .versions(|row| match most_recent.entry(row.crate_id) {
27            Entry::Vacant(entry) => {
28                entry.insert(row);
29            }
30            Entry::Occupied(mut entry) => {
31                if row.created_at > entry.get().created_at {
32                    entry.insert(row);
33                }
34            }
35        })
36        .load("./db-dump.tar.gz")?;
37
38    // Set of version ids which are the most recently published of their crate.
39    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41    // Set of (version id, dependency crate id) pairs to avoid double-counting
42    // cases where a crate has both a normal dependency and dev-dependency or
43    // build-dependency on the same dependency crate.
44    let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46    // Map of crate id to how many other crates' most recent version depends on
47    // that crate.
48    let mut count = Map::<CrateId, usize>::new();
49    for dep in dependencies {
50        if most_recent.contains(&dep.version_id)
51            && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52        {
53            *count.entry(dep.crate_id).or_default() += 1;
54        }
55    }
56
57    // Quickselect and sort the top N crates by reverse dependency count.
58    let mut sort = Vec::from_iter(count);
59    let sort_by_count = |&(_crate, count): &_| Reverse(count);
60    sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61    sort[..N].sort_unstable_by_key(sort_by_count);
62
63    for (id, count) in sort.iter().take(N) {
64        let crate_name = &crates.get(id).unwrap().name;
65        println!("{},{}", crate_name, count);
66    }
67
68    Ok(())
69}
examples/user-dependencies-graph.rs (lines 22-27)
10fn main() -> db_dump::Result<()> {
11    let mut user_id = None;
12    let mut crate_owners = Vec::new();
13    let mut dependencies = Map::new();
14    let mut versions = Vec::new();
15    db_dump::Loader::new()
16        .users(|row| {
17            if row.gh_login == USER {
18                user_id = Some(row.id);
19            }
20        })
21        .crate_owners(|row| crate_owners.push(row))
22        .dependencies(|row| {
23            dependencies
24                .entry(row.version_id)
25                .or_insert_with(Vec::new)
26                .push(row);
27        })
28        .versions(|row| {
29            if !row.yanked {
30                versions.push(row);
31            }
32        })
33        .load("./db-dump.tar.gz")?;
34
35    // User id of the crate author we care about.
36    let user_id = user_id.expect("no such user");
37
38    // Set of crate ids currently owned by that user.
39    let mut their_crates = Set::new();
40    for crate_owner in crate_owners {
41        if crate_owner.owner_id == user_id {
42            their_crates.insert(crate_owner.crate_id);
43        }
44    }
45
46    let mut total_deps = 0usize;
47    let mut their_deps = 0usize;
48    let mut last_printed_ratio = 0.0..=0.0;
49    let mut latest_version = Map::new();
50
51    versions.sort_by_key(|v| v.created_at);
52
53    for version in versions {
54        let no_deps = Vec::new();
55        if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56            for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57                total_deps -= 1;
58                their_deps -= their_crates.contains(&dep.crate_id) as usize;
59            }
60        }
61        for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62            total_deps += 1;
63            their_deps += their_crates.contains(&dep.crate_id) as usize;
64        }
65        if total_deps != 0 {
66            let ratio = their_deps as f64 / total_deps as f64;
67            if !last_printed_ratio.contains(&ratio) {
68                println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69                last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70            }
71        }
72    }
73
74    eprintln!(
75        "{} / {} ({:.02}%)",
76        their_deps,
77        total_deps,
78        (their_deps as f64 / total_deps as f64) * 100.0,
79    );
80    Ok(())
81}
Source

pub fn keywords(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Source

pub fn metadata(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Source

pub fn reserved_crate_names(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Source

pub fn teams(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Source

pub fn users(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Examples found in repository?
examples/user-downloads.rs (lines 24-28)
18fn main() -> db_dump::Result<()> {
19    let mut user_id = None;
20    let mut crate_owners = Vec::new();
21    let mut versions = Vec::new();
22    let mut version_downloads = Vec::new();
23    db_dump::Loader::new()
24        .users(|row| {
25            if row.gh_login == USER {
26                user_id = Some(row.id);
27            }
28        })
29        .crate_owners(|row| crate_owners.push(row))
30        .versions(|row| versions.push(row))
31        .version_downloads(|row| version_downloads.push(row))
32        .load("./db-dump.tar.gz")?;
33
34    // User id of the crate author we care about.
35    let user_id = user_id.expect("no such user");
36
37    // Set of crate ids currently owned by that user.
38    let mut their_crates = Set::new();
39    for crate_owner in crate_owners {
40        if crate_owner.owner_id == user_id {
41            their_crates.insert(crate_owner.crate_id);
42        }
43    }
44
45    // Set of version ids of all of those crates.
46    let mut their_versions = Set::new();
47    for version in versions {
48        if their_crates.contains(&version.crate_id) {
49            their_versions.insert(version.id);
50        }
51    }
52
53    // Add up downloads across that user's crates, as well as total downloads of
54    // all crates.
55    let mut downloads = Map::<Date<Utc>, Downloads>::new();
56    for stat in version_downloads {
57        let entry = downloads.entry(stat.date).or_default();
58        entry.all += stat.downloads;
59        if their_versions.contains(&stat.version_id) {
60            entry.theirs += stat.downloads;
61        }
62    }
63
64    // Print user's downloads as a fraction of total crates.io downloads by day.
65    for (date, downloads) in downloads {
66        if downloads.theirs > 0 {
67            println!(
68                "{},{}",
69                date,
70                downloads.theirs as f64 / downloads.all as f64,
71            );
72        }
73    }
74
75    Ok(())
76}
More examples
Hide additional examples
examples/user-dependencies.rs (lines 20-24)
11fn main() -> db_dump::Result<()> {
12    // Map of crate id to the most recently published version of that crate.
13    let mut most_recent = Map::new();
14
15    let mut user_id = None;
16    let mut crates = 0;
17    let mut crate_owners = Vec::new();
18    let mut dependencies = Vec::new();
19    db_dump::Loader::new()
20        .users(|row| {
21            if row.gh_login == USER {
22                user_id = Some(row.id);
23            }
24        })
25        .crates(|_row| crates += 1)
26        .crate_owners(|row| crate_owners.push(row))
27        .dependencies(|row| dependencies.push(row))
28        .versions(|row| match most_recent.entry(row.crate_id) {
29            Entry::Vacant(entry) => {
30                entry.insert(row);
31            }
32            Entry::Occupied(mut entry) => {
33                if row.created_at > entry.get().created_at {
34                    entry.insert(row);
35                }
36            }
37        })
38        .load("./db-dump.tar.gz")?;
39
40    // User id of the crate author we care about.
41    let user_id = user_id.expect("no such user");
42
43    // Set of crate ids currently owned by that user.
44    let mut their_crates = Set::new();
45    for crate_owner in crate_owners {
46        if crate_owner.owner_id == user_id {
47            their_crates.insert(crate_owner.crate_id);
48        }
49    }
50
51    // Set of version ids which are the most recently published of their crate.
52    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54    // Set of version ids which depend directly on at least one crate by the
55    // user.
56    let mut dep_on_them = Set::new();
57    for dep in dependencies {
58        if their_crates.contains(&dep.crate_id) {
59            dep_on_them.insert(dep.version_id);
60        }
61    }
62
63    // Number of crates whose most recent version depends on at least one crate
64    // by the user.
65    let result = dep_on_them.intersection(&most_recent).count();
66
67    println!(
68        "{} / {} = {:.1}%",
69        result,
70        crates,
71        100.0 * result as f64 / crates as f64,
72    );
73
74    Ok(())
75}
examples/user-dependencies-graph.rs (lines 16-20)
10fn main() -> db_dump::Result<()> {
11    let mut user_id = None;
12    let mut crate_owners = Vec::new();
13    let mut dependencies = Map::new();
14    let mut versions = Vec::new();
15    db_dump::Loader::new()
16        .users(|row| {
17            if row.gh_login == USER {
18                user_id = Some(row.id);
19            }
20        })
21        .crate_owners(|row| crate_owners.push(row))
22        .dependencies(|row| {
23            dependencies
24                .entry(row.version_id)
25                .or_insert_with(Vec::new)
26                .push(row);
27        })
28        .versions(|row| {
29            if !row.yanked {
30                versions.push(row);
31            }
32        })
33        .load("./db-dump.tar.gz")?;
34
35    // User id of the crate author we care about.
36    let user_id = user_id.expect("no such user");
37
38    // Set of crate ids currently owned by that user.
39    let mut their_crates = Set::new();
40    for crate_owner in crate_owners {
41        if crate_owner.owner_id == user_id {
42            their_crates.insert(crate_owner.crate_id);
43        }
44    }
45
46    let mut total_deps = 0usize;
47    let mut their_deps = 0usize;
48    let mut last_printed_ratio = 0.0..=0.0;
49    let mut latest_version = Map::new();
50
51    versions.sort_by_key(|v| v.created_at);
52
53    for version in versions {
54        let no_deps = Vec::new();
55        if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56            for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57                total_deps -= 1;
58                their_deps -= their_crates.contains(&dep.crate_id) as usize;
59            }
60        }
61        for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62            total_deps += 1;
63            their_deps += their_crates.contains(&dep.crate_id) as usize;
64        }
65        if total_deps != 0 {
66            let ratio = their_deps as f64 / total_deps as f64;
67            if !last_printed_ratio.contains(&ratio) {
68                println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69                last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70            }
71        }
72    }
73
74    eprintln!(
75        "{} / {} ({:.02}%)",
76        their_deps,
77        total_deps,
78        (their_deps as f64 / total_deps as f64) * 100.0,
79    );
80    Ok(())
81}
Source

pub fn version_downloads(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Examples found in repository?
examples/total-downloads.rs (lines 13-15)
10fn main() -> db_dump::Result<()> {
11    let mut downloads = Map::<Date<Utc>, u64>::new();
12    db_dump::Loader::new()
13        .version_downloads(|row| {
14            *downloads.entry(row.date).or_default() += row.downloads;
15        })
16        .load("./db-dump.tar.gz")?;
17
18    for (date, count) in downloads {
19        println!("{},{}", date, count);
20    }
21
22    Ok(())
23}
More examples
Hide additional examples
examples/crate-downloads.rs (line 22)
11fn main() -> db_dump::Result<()> {
12    let mut crate_id = None;
13    let mut versions = Vec::new();
14    let mut version_downloads = Vec::new();
15    db_dump::Loader::new()
16        .crates(|row| {
17            if row.name == CRATE {
18                crate_id = Some(row.id);
19            }
20        })
21        .versions(|row| versions.push(row))
22        .version_downloads(|row| version_downloads.push(row))
23        .load("./db-dump.tar.gz")?;
24
25    // Crate id of the crate we care about.
26    let crate_id = crate_id.expect("no such crate");
27
28    // Set of all version ids corresponding to that crate.
29    let mut version_ids = Set::new();
30    for version in versions {
31        if version.crate_id == crate_id {
32            version_ids.insert(version.id);
33        }
34    }
35
36    // Add up downloads across all version of the crate by day.
37    let mut downloads = Map::<Date<Utc>, u64>::new();
38    for stat in version_downloads {
39        if version_ids.contains(&stat.version_id) {
40            *downloads.entry(stat.date).or_default() += stat.downloads;
41        }
42    }
43
44    for (date, count) in downloads {
45        println!("{},{}", date, count);
46    }
47
48    Ok(())
49}
examples/user-downloads.rs (line 31)
18fn main() -> db_dump::Result<()> {
19    let mut user_id = None;
20    let mut crate_owners = Vec::new();
21    let mut versions = Vec::new();
22    let mut version_downloads = Vec::new();
23    db_dump::Loader::new()
24        .users(|row| {
25            if row.gh_login == USER {
26                user_id = Some(row.id);
27            }
28        })
29        .crate_owners(|row| crate_owners.push(row))
30        .versions(|row| versions.push(row))
31        .version_downloads(|row| version_downloads.push(row))
32        .load("./db-dump.tar.gz")?;
33
34    // User id of the crate author we care about.
35    let user_id = user_id.expect("no such user");
36
37    // Set of crate ids currently owned by that user.
38    let mut their_crates = Set::new();
39    for crate_owner in crate_owners {
40        if crate_owner.owner_id == user_id {
41            their_crates.insert(crate_owner.crate_id);
42        }
43    }
44
45    // Set of version ids of all of those crates.
46    let mut their_versions = Set::new();
47    for version in versions {
48        if their_crates.contains(&version.crate_id) {
49            their_versions.insert(version.id);
50        }
51    }
52
53    // Add up downloads across that user's crates, as well as total downloads of
54    // all crates.
55    let mut downloads = Map::<Date<Utc>, Downloads>::new();
56    for stat in version_downloads {
57        let entry = downloads.entry(stat.date).or_default();
58        entry.all += stat.downloads;
59        if their_versions.contains(&stat.version_id) {
60            entry.theirs += stat.downloads;
61        }
62    }
63
64    // Print user's downloads as a fraction of total crates.io downloads by day.
65    for (date, downloads) in downloads {
66        if downloads.theirs > 0 {
67            println!(
68                "{},{}",
69                date,
70                downloads.theirs as f64 / downloads.all as f64,
71            );
72        }
73    }
74
75    Ok(())
76}
examples/industry-coefficient.rs (line 31)
20fn main() -> db_dump::Result<()> {
21    let mut crates: Map<CrateId, String> = Map::new();
22    let mut versions: Map<VersionId, CrateId> = Map::new();
23    let mut version_downloads = Vec::new();
24    db_dump::Loader::new()
25        .crates(|row| {
26            crates.insert(row.id, row.name);
27        })
28        .versions(|row| {
29            versions.insert(row.id, row.crate_id);
30        })
31        .version_downloads(|row| version_downloads.push(row))
32        .load("./db-dump.tar.gz")?;
33
34    let max_date = version_downloads.iter().map(|row| row.date).max().unwrap();
35    let start_date = max_date - TimeDelta::try_weeks(6).unwrap();
36
37    // Add up downloads by crate by date
38    let mut downloads: Map<CrateId, Downloads> = Map::new();
39    for row in version_downloads {
40        // Deliberately cut out the largest date in the db-dump, because the
41        // data is partial.
42        if row.date >= start_date && row.date < max_date {
43            let crate_id = versions[&row.version_id];
44            let downloads = downloads.entry(crate_id).or_insert_with(Downloads::default);
45            match row.date.weekday() {
46                Weekday::Tue | Weekday::Wed | Weekday::Thu => downloads.weekday += row.downloads,
47                Weekday::Sat | Weekday::Sun => downloads.weekend += row.downloads,
48                // Disregard these to reduce some boundary effect from
49                // downloaders not being perfectly aligned with UTC.
50                Weekday::Mon | Weekday::Fri => {}
51            }
52        }
53    }
54
55    let mut downloads_vec = Vec::new();
56    let mut total = Downloads::default();
57    for (crate_id, downloads) in downloads {
58        total.weekday += downloads.weekday;
59        total.weekend += downloads.weekend;
60        let crate_name = &crates[&crate_id];
61        if downloads.weekend > 0
62            && (downloads.weekday + downloads.weekend >= DOWNLOADS_CUTOFF || crate_name == "cxx")
63        {
64            let coefficient = downloads.weekday as f64 / downloads.weekend as f64;
65            downloads_vec.push((crate_name, coefficient));
66        }
67    }
68
69    let mean = total.weekday as f64 / total.weekend as f64;
70    downloads_vec.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
71
72    for (crate_name, coefficient) in downloads_vec {
73        println!("{:>36}  {:+.4}", crate_name, coefficient - mean);
74    }
75
76    Ok(())
77}
Source

pub fn versions(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self

Examples found in repository?
examples/crate-downloads.rs (line 21)
11fn main() -> db_dump::Result<()> {
12    let mut crate_id = None;
13    let mut versions = Vec::new();
14    let mut version_downloads = Vec::new();
15    db_dump::Loader::new()
16        .crates(|row| {
17            if row.name == CRATE {
18                crate_id = Some(row.id);
19            }
20        })
21        .versions(|row| versions.push(row))
22        .version_downloads(|row| version_downloads.push(row))
23        .load("./db-dump.tar.gz")?;
24
25    // Crate id of the crate we care about.
26    let crate_id = crate_id.expect("no such crate");
27
28    // Set of all version ids corresponding to that crate.
29    let mut version_ids = Set::new();
30    for version in versions {
31        if version.crate_id == crate_id {
32            version_ids.insert(version.id);
33        }
34    }
35
36    // Add up downloads across all version of the crate by day.
37    let mut downloads = Map::<Date<Utc>, u64>::new();
38    for stat in version_downloads {
39        if version_ids.contains(&stat.version_id) {
40            *downloads.entry(stat.date).or_default() += stat.downloads;
41        }
42    }
43
44    for (date, count) in downloads {
45        println!("{},{}", date, count);
46    }
47
48    Ok(())
49}
More examples
Hide additional examples
examples/user-downloads.rs (line 30)
18fn main() -> db_dump::Result<()> {
19    let mut user_id = None;
20    let mut crate_owners = Vec::new();
21    let mut versions = Vec::new();
22    let mut version_downloads = Vec::new();
23    db_dump::Loader::new()
24        .users(|row| {
25            if row.gh_login == USER {
26                user_id = Some(row.id);
27            }
28        })
29        .crate_owners(|row| crate_owners.push(row))
30        .versions(|row| versions.push(row))
31        .version_downloads(|row| version_downloads.push(row))
32        .load("./db-dump.tar.gz")?;
33
34    // User id of the crate author we care about.
35    let user_id = user_id.expect("no such user");
36
37    // Set of crate ids currently owned by that user.
38    let mut their_crates = Set::new();
39    for crate_owner in crate_owners {
40        if crate_owner.owner_id == user_id {
41            their_crates.insert(crate_owner.crate_id);
42        }
43    }
44
45    // Set of version ids of all of those crates.
46    let mut their_versions = Set::new();
47    for version in versions {
48        if their_crates.contains(&version.crate_id) {
49            their_versions.insert(version.id);
50        }
51    }
52
53    // Add up downloads across that user's crates, as well as total downloads of
54    // all crates.
55    let mut downloads = Map::<Date<Utc>, Downloads>::new();
56    for stat in version_downloads {
57        let entry = downloads.entry(stat.date).or_default();
58        entry.all += stat.downloads;
59        if their_versions.contains(&stat.version_id) {
60            entry.theirs += stat.downloads;
61        }
62    }
63
64    // Print user's downloads as a fraction of total crates.io downloads by day.
65    for (date, downloads) in downloads {
66        if downloads.theirs > 0 {
67            println!(
68                "{},{}",
69                date,
70                downloads.theirs as f64 / downloads.all as f64,
71            );
72        }
73    }
74
75    Ok(())
76}
examples/user-dependencies.rs (lines 28-37)
11fn main() -> db_dump::Result<()> {
12    // Map of crate id to the most recently published version of that crate.
13    let mut most_recent = Map::new();
14
15    let mut user_id = None;
16    let mut crates = 0;
17    let mut crate_owners = Vec::new();
18    let mut dependencies = Vec::new();
19    db_dump::Loader::new()
20        .users(|row| {
21            if row.gh_login == USER {
22                user_id = Some(row.id);
23            }
24        })
25        .crates(|_row| crates += 1)
26        .crate_owners(|row| crate_owners.push(row))
27        .dependencies(|row| dependencies.push(row))
28        .versions(|row| match most_recent.entry(row.crate_id) {
29            Entry::Vacant(entry) => {
30                entry.insert(row);
31            }
32            Entry::Occupied(mut entry) => {
33                if row.created_at > entry.get().created_at {
34                    entry.insert(row);
35                }
36            }
37        })
38        .load("./db-dump.tar.gz")?;
39
40    // User id of the crate author we care about.
41    let user_id = user_id.expect("no such user");
42
43    // Set of crate ids currently owned by that user.
44    let mut their_crates = Set::new();
45    for crate_owner in crate_owners {
46        if crate_owner.owner_id == user_id {
47            their_crates.insert(crate_owner.crate_id);
48        }
49    }
50
51    // Set of version ids which are the most recently published of their crate.
52    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54    // Set of version ids which depend directly on at least one crate by the
55    // user.
56    let mut dep_on_them = Set::new();
57    for dep in dependencies {
58        if their_crates.contains(&dep.crate_id) {
59            dep_on_them.insert(dep.version_id);
60        }
61    }
62
63    // Number of crates whose most recent version depends on at least one crate
64    // by the user.
65    let result = dep_on_them.intersection(&most_recent).count();
66
67    println!(
68        "{} / {} = {:.1}%",
69        result,
70        crates,
71        100.0 * result as f64 / crates as f64,
72    );
73
74    Ok(())
75}
examples/top-crates.rs (lines 26-35)
13fn main() -> db_dump::Result<()> {
14    // Map of crate id to the most recently published version of that crate.
15    let mut most_recent = Map::new();
16
17    let mut crates = Set::new();
18    let mut crate_owners = Vec::new();
19    let mut dependencies = Vec::new();
20    db_dump::Loader::new()
21        .crates(|row| {
22            crates.insert(row);
23        })
24        .crate_owners(|row| crate_owners.push(row))
25        .dependencies(|row| dependencies.push(row))
26        .versions(|row| match most_recent.entry(row.crate_id) {
27            Entry::Vacant(entry) => {
28                entry.insert(row);
29            }
30            Entry::Occupied(mut entry) => {
31                if row.created_at > entry.get().created_at {
32                    entry.insert(row);
33                }
34            }
35        })
36        .load("./db-dump.tar.gz")?;
37
38    // Set of version ids which are the most recently published of their crate.
39    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41    // Set of (version id, dependency crate id) pairs to avoid double-counting
42    // cases where a crate has both a normal dependency and dev-dependency or
43    // build-dependency on the same dependency crate.
44    let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46    // Map of crate id to how many other crates' most recent version depends on
47    // that crate.
48    let mut count = Map::<CrateId, usize>::new();
49    for dep in dependencies {
50        if most_recent.contains(&dep.version_id)
51            && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52        {
53            *count.entry(dep.crate_id).or_default() += 1;
54        }
55    }
56
57    // Quickselect and sort the top N crates by reverse dependency count.
58    let mut sort = Vec::from_iter(count);
59    let sort_by_count = |&(_crate, count): &_| Reverse(count);
60    sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61    sort[..N].sort_unstable_by_key(sort_by_count);
62
63    for (id, count) in sort.iter().take(N) {
64        let crate_name = &crates.get(id).unwrap().name;
65        println!("{},{}", crate_name, count);
66    }
67
68    Ok(())
69}
examples/user-dependencies-graph.rs (lines 28-32)
10fn main() -> db_dump::Result<()> {
11    let mut user_id = None;
12    let mut crate_owners = Vec::new();
13    let mut dependencies = Map::new();
14    let mut versions = Vec::new();
15    db_dump::Loader::new()
16        .users(|row| {
17            if row.gh_login == USER {
18                user_id = Some(row.id);
19            }
20        })
21        .crate_owners(|row| crate_owners.push(row))
22        .dependencies(|row| {
23            dependencies
24                .entry(row.version_id)
25                .or_insert_with(Vec::new)
26                .push(row);
27        })
28        .versions(|row| {
29            if !row.yanked {
30                versions.push(row);
31            }
32        })
33        .load("./db-dump.tar.gz")?;
34
35    // User id of the crate author we care about.
36    let user_id = user_id.expect("no such user");
37
38    // Set of crate ids currently owned by that user.
39    let mut their_crates = Set::new();
40    for crate_owner in crate_owners {
41        if crate_owner.owner_id == user_id {
42            their_crates.insert(crate_owner.crate_id);
43        }
44    }
45
46    let mut total_deps = 0usize;
47    let mut their_deps = 0usize;
48    let mut last_printed_ratio = 0.0..=0.0;
49    let mut latest_version = Map::new();
50
51    versions.sort_by_key(|v| v.created_at);
52
53    for version in versions {
54        let no_deps = Vec::new();
55        if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56            for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57                total_deps -= 1;
58                their_deps -= their_crates.contains(&dep.crate_id) as usize;
59            }
60        }
61        for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62            total_deps += 1;
63            their_deps += their_crates.contains(&dep.crate_id) as usize;
64        }
65        if total_deps != 0 {
66            let ratio = their_deps as f64 / total_deps as f64;
67            if !last_printed_ratio.contains(&ratio) {
68                println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69                last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70            }
71        }
72    }
73
74    eprintln!(
75        "{} / {} ({:.02}%)",
76        their_deps,
77        total_deps,
78        (their_deps as f64 / total_deps as f64) * 100.0,
79    );
80    Ok(())
81}
examples/industry-coefficient.rs (lines 28-30)
20fn main() -> db_dump::Result<()> {
21    let mut crates: Map<CrateId, String> = Map::new();
22    let mut versions: Map<VersionId, CrateId> = Map::new();
23    let mut version_downloads = Vec::new();
24    db_dump::Loader::new()
25        .crates(|row| {
26            crates.insert(row.id, row.name);
27        })
28        .versions(|row| {
29            versions.insert(row.id, row.crate_id);
30        })
31        .version_downloads(|row| version_downloads.push(row))
32        .load("./db-dump.tar.gz")?;
33
34    let max_date = version_downloads.iter().map(|row| row.date).max().unwrap();
35    let start_date = max_date - TimeDelta::try_weeks(6).unwrap();
36
37    // Add up downloads by crate by date
38    let mut downloads: Map<CrateId, Downloads> = Map::new();
39    for row in version_downloads {
40        // Deliberately cut out the largest date in the db-dump, because the
41        // data is partial.
42        if row.date >= start_date && row.date < max_date {
43            let crate_id = versions[&row.version_id];
44            let downloads = downloads.entry(crate_id).or_insert_with(Downloads::default);
45            match row.date.weekday() {
46                Weekday::Tue | Weekday::Wed | Weekday::Thu => downloads.weekday += row.downloads,
47                Weekday::Sat | Weekday::Sun => downloads.weekend += row.downloads,
48                // Disregard these to reduce some boundary effect from
49                // downloaders not being perfectly aligned with UTC.
50                Weekday::Mon | Weekday::Fri => {}
51            }
52        }
53    }
54
55    let mut downloads_vec = Vec::new();
56    let mut total = Downloads::default();
57    for (crate_id, downloads) in downloads {
58        total.weekday += downloads.weekday;
59        total.weekend += downloads.weekend;
60        let crate_name = &crates[&crate_id];
61        if downloads.weekend > 0
62            && (downloads.weekday + downloads.weekend >= DOWNLOADS_CUTOFF || crate_name == "cxx")
63        {
64            let coefficient = downloads.weekday as f64 / downloads.weekend as f64;
65            downloads_vec.push((crate_name, coefficient));
66        }
67    }
68
69    let mean = total.weekday as f64 / total.weekend as f64;
70    downloads_vec.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
71
72    for (crate_name, coefficient) in downloads_vec {
73        println!("{:>36}  {:+.4}", crate_name, coefficient - mean);
74    }
75
76    Ok(())
77}
Source

pub fn load(&mut self, path: impl AsRef<Path>) -> Result<()>

Examples found in repository?
examples/total-downloads.rs (line 16)
10fn main() -> db_dump::Result<()> {
11    let mut downloads = Map::<Date<Utc>, u64>::new();
12    db_dump::Loader::new()
13        .version_downloads(|row| {
14            *downloads.entry(row.date).or_default() += row.downloads;
15        })
16        .load("./db-dump.tar.gz")?;
17
18    for (date, count) in downloads {
19        println!("{},{}", date, count);
20    }
21
22    Ok(())
23}
More examples
Hide additional examples
examples/crate-downloads.rs (line 23)
11fn main() -> db_dump::Result<()> {
12    let mut crate_id = None;
13    let mut versions = Vec::new();
14    let mut version_downloads = Vec::new();
15    db_dump::Loader::new()
16        .crates(|row| {
17            if row.name == CRATE {
18                crate_id = Some(row.id);
19            }
20        })
21        .versions(|row| versions.push(row))
22        .version_downloads(|row| version_downloads.push(row))
23        .load("./db-dump.tar.gz")?;
24
25    // Crate id of the crate we care about.
26    let crate_id = crate_id.expect("no such crate");
27
28    // Set of all version ids corresponding to that crate.
29    let mut version_ids = Set::new();
30    for version in versions {
31        if version.crate_id == crate_id {
32            version_ids.insert(version.id);
33        }
34    }
35
36    // Add up downloads across all version of the crate by day.
37    let mut downloads = Map::<Date<Utc>, u64>::new();
38    for stat in version_downloads {
39        if version_ids.contains(&stat.version_id) {
40            *downloads.entry(stat.date).or_default() += stat.downloads;
41        }
42    }
43
44    for (date, count) in downloads {
45        println!("{},{}", date, count);
46    }
47
48    Ok(())
49}
examples/user-downloads.rs (line 32)
18fn main() -> db_dump::Result<()> {
19    let mut user_id = None;
20    let mut crate_owners = Vec::new();
21    let mut versions = Vec::new();
22    let mut version_downloads = Vec::new();
23    db_dump::Loader::new()
24        .users(|row| {
25            if row.gh_login == USER {
26                user_id = Some(row.id);
27            }
28        })
29        .crate_owners(|row| crate_owners.push(row))
30        .versions(|row| versions.push(row))
31        .version_downloads(|row| version_downloads.push(row))
32        .load("./db-dump.tar.gz")?;
33
34    // User id of the crate author we care about.
35    let user_id = user_id.expect("no such user");
36
37    // Set of crate ids currently owned by that user.
38    let mut their_crates = Set::new();
39    for crate_owner in crate_owners {
40        if crate_owner.owner_id == user_id {
41            their_crates.insert(crate_owner.crate_id);
42        }
43    }
44
45    // Set of version ids of all of those crates.
46    let mut their_versions = Set::new();
47    for version in versions {
48        if their_crates.contains(&version.crate_id) {
49            their_versions.insert(version.id);
50        }
51    }
52
53    // Add up downloads across that user's crates, as well as total downloads of
54    // all crates.
55    let mut downloads = Map::<Date<Utc>, Downloads>::new();
56    for stat in version_downloads {
57        let entry = downloads.entry(stat.date).or_default();
58        entry.all += stat.downloads;
59        if their_versions.contains(&stat.version_id) {
60            entry.theirs += stat.downloads;
61        }
62    }
63
64    // Print user's downloads as a fraction of total crates.io downloads by day.
65    for (date, downloads) in downloads {
66        if downloads.theirs > 0 {
67            println!(
68                "{},{}",
69                date,
70                downloads.theirs as f64 / downloads.all as f64,
71            );
72        }
73    }
74
75    Ok(())
76}
examples/user-dependencies.rs (line 38)
11fn main() -> db_dump::Result<()> {
12    // Map of crate id to the most recently published version of that crate.
13    let mut most_recent = Map::new();
14
15    let mut user_id = None;
16    let mut crates = 0;
17    let mut crate_owners = Vec::new();
18    let mut dependencies = Vec::new();
19    db_dump::Loader::new()
20        .users(|row| {
21            if row.gh_login == USER {
22                user_id = Some(row.id);
23            }
24        })
25        .crates(|_row| crates += 1)
26        .crate_owners(|row| crate_owners.push(row))
27        .dependencies(|row| dependencies.push(row))
28        .versions(|row| match most_recent.entry(row.crate_id) {
29            Entry::Vacant(entry) => {
30                entry.insert(row);
31            }
32            Entry::Occupied(mut entry) => {
33                if row.created_at > entry.get().created_at {
34                    entry.insert(row);
35                }
36            }
37        })
38        .load("./db-dump.tar.gz")?;
39
40    // User id of the crate author we care about.
41    let user_id = user_id.expect("no such user");
42
43    // Set of crate ids currently owned by that user.
44    let mut their_crates = Set::new();
45    for crate_owner in crate_owners {
46        if crate_owner.owner_id == user_id {
47            their_crates.insert(crate_owner.crate_id);
48        }
49    }
50
51    // Set of version ids which are the most recently published of their crate.
52    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54    // Set of version ids which depend directly on at least one crate by the
55    // user.
56    let mut dep_on_them = Set::new();
57    for dep in dependencies {
58        if their_crates.contains(&dep.crate_id) {
59            dep_on_them.insert(dep.version_id);
60        }
61    }
62
63    // Number of crates whose most recent version depends on at least one crate
64    // by the user.
65    let result = dep_on_them.intersection(&most_recent).count();
66
67    println!(
68        "{} / {} = {:.1}%",
69        result,
70        crates,
71        100.0 * result as f64 / crates as f64,
72    );
73
74    Ok(())
75}
examples/top-crates.rs (line 36)
13fn main() -> db_dump::Result<()> {
14    // Map of crate id to the most recently published version of that crate.
15    let mut most_recent = Map::new();
16
17    let mut crates = Set::new();
18    let mut crate_owners = Vec::new();
19    let mut dependencies = Vec::new();
20    db_dump::Loader::new()
21        .crates(|row| {
22            crates.insert(row);
23        })
24        .crate_owners(|row| crate_owners.push(row))
25        .dependencies(|row| dependencies.push(row))
26        .versions(|row| match most_recent.entry(row.crate_id) {
27            Entry::Vacant(entry) => {
28                entry.insert(row);
29            }
30            Entry::Occupied(mut entry) => {
31                if row.created_at > entry.get().created_at {
32                    entry.insert(row);
33                }
34            }
35        })
36        .load("./db-dump.tar.gz")?;
37
38    // Set of version ids which are the most recently published of their crate.
39    let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41    // Set of (version id, dependency crate id) pairs to avoid double-counting
42    // cases where a crate has both a normal dependency and dev-dependency or
43    // build-dependency on the same dependency crate.
44    let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46    // Map of crate id to how many other crates' most recent version depends on
47    // that crate.
48    let mut count = Map::<CrateId, usize>::new();
49    for dep in dependencies {
50        if most_recent.contains(&dep.version_id)
51            && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52        {
53            *count.entry(dep.crate_id).or_default() += 1;
54        }
55    }
56
57    // Quickselect and sort the top N crates by reverse dependency count.
58    let mut sort = Vec::from_iter(count);
59    let sort_by_count = |&(_crate, count): &_| Reverse(count);
60    sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61    sort[..N].sort_unstable_by_key(sort_by_count);
62
63    for (id, count) in sort.iter().take(N) {
64        let crate_name = &crates.get(id).unwrap().name;
65        println!("{},{}", crate_name, count);
66    }
67
68    Ok(())
69}
examples/user-dependencies-graph.rs (line 33)
10fn main() -> db_dump::Result<()> {
11    let mut user_id = None;
12    let mut crate_owners = Vec::new();
13    let mut dependencies = Map::new();
14    let mut versions = Vec::new();
15    db_dump::Loader::new()
16        .users(|row| {
17            if row.gh_login == USER {
18                user_id = Some(row.id);
19            }
20        })
21        .crate_owners(|row| crate_owners.push(row))
22        .dependencies(|row| {
23            dependencies
24                .entry(row.version_id)
25                .or_insert_with(Vec::new)
26                .push(row);
27        })
28        .versions(|row| {
29            if !row.yanked {
30                versions.push(row);
31            }
32        })
33        .load("./db-dump.tar.gz")?;
34
35    // User id of the crate author we care about.
36    let user_id = user_id.expect("no such user");
37
38    // Set of crate ids currently owned by that user.
39    let mut their_crates = Set::new();
40    for crate_owner in crate_owners {
41        if crate_owner.owner_id == user_id {
42            their_crates.insert(crate_owner.crate_id);
43        }
44    }
45
46    let mut total_deps = 0usize;
47    let mut their_deps = 0usize;
48    let mut last_printed_ratio = 0.0..=0.0;
49    let mut latest_version = Map::new();
50
51    versions.sort_by_key(|v| v.created_at);
52
53    for version in versions {
54        let no_deps = Vec::new();
55        if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56            for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57                total_deps -= 1;
58                their_deps -= their_crates.contains(&dep.crate_id) as usize;
59            }
60        }
61        for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62            total_deps += 1;
63            their_deps += their_crates.contains(&dep.crate_id) as usize;
64        }
65        if total_deps != 0 {
66            let ratio = their_deps as f64 / total_deps as f64;
67            if !last_printed_ratio.contains(&ratio) {
68                println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69                last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70            }
71        }
72    }
73
74    eprintln!(
75        "{} / {} ({:.02}%)",
76        their_deps,
77        total_deps,
78        (their_deps as f64 / total_deps as f64) * 100.0,
79    );
80    Ok(())
81}

Trait Implementations§

Source§

impl<'a> Default for Loader<'a>

Source§

fn default() -> Loader<'a>

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for Loader<'a>

§

impl<'a> !RefUnwindSafe for Loader<'a>

§

impl<'a> !Send for Loader<'a>

§

impl<'a> !Sync for Loader<'a>

§

impl<'a> Unpin for Loader<'a>

§

impl<'a> !UnwindSafe for Loader<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.