1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* Each test should first create a table with two columns, insert 8,192 identical rows 'Alice', 1000.
   Then (the timed part) should total the second column ( result 8,192,000 ) and do this 1,000 times.
*/

#[test]
fn sqlite_test() {
    let connection = sqlite::open(":memory:").unwrap();

    let sql = "
    CREATE TABLE users (Id INTEGER PRIMARY KEY, name TEXT, age INTEGER);
    INSERT INTO users(name,age) VALUES ('Alice', 1000);";
    connection.execute(sql).unwrap();

    let sql = "INSERT INTO users(name,age) SELECT name, age FROM users";

    // Create 8192 records (each iteration should double number of records)
    for _i in 0..13 {
        connection.execute(sql).unwrap();
    }

    let mut results = Vec::new();
    for _outer in 0..100 {
        let start = std::time::Instant::now();
        for _i in 0..10 {
            let sql = "SELECT SUM(age) FROM users";
            connection.execute(sql).unwrap();
        }
        results.push(start.elapsed().as_micros() as u64);
    }
    print_results("sqlite_test", results);
}

#[test]
fn rustdb_test() {
    use crate::*;

    // let stg = AtomicFile::new(MemFile::new(), DummyFile::new());
    let stg = MemFile::new();

    let mut bmap = BuiltinMap::default();
    standard_builtins(&mut bmap);
    let bmap = Arc::new(bmap);

    let spd = SharedPagedData::new(stg);
    let wapd = AccessPagedData::new_writer(spd.clone());
    let db = Database::new(wapd, "", bmap.clone());

    let mut tr = GenTransaction::default();

    let sql = "
    CREATE SCHEMA test GO
    CREATE TABLE test.users (name string, age int) GO";

    db.run(&sql, &mut tr);

    let sql = "DECLARE @i int SET @i = 8192
      WHILE @i > 0
      BEGIN
        INSERT INTO test.users(name,age) VALUES ('Alice', 1000)
        SET @i -= 1
      END";

    db.run(&sql, &mut tr);

    let mut results = Vec::new();
    for _outer in 0..100 {
        let start = std::time::Instant::now();

        for _i in 0..10 {
            let sql =
                "DECLARE @total int FOR @total += age FROM test.users BEGIN END SELECT ''|@total";
            let mut tr = GenTransaction::default();
            db.run(&sql, &mut tr);
            assert_eq!(tr.rp.output, b"8192000");
        }

        results.push(start.elapsed().as_micros() as u64);
    }
    print_results("rustdb_test", results);
}

#[test]
fn rustdb_direct_test() {
    use crate::*;

    // let stg = AtomicFile::new(MemFile::new(), MemFile::new());
    let stg = MemFile::new();

    let mut bmap = BuiltinMap::default();
    standard_builtins(&mut bmap);
    let bmap = Arc::new(bmap);

    let spd = SharedPagedData::new(stg);
    let wapd = AccessPagedData::new_writer(spd.clone());

    let db = Database::new(wapd, "", bmap.clone());

    let mut tr = GenTransaction::default();

    let sql = "
    CREATE SCHEMA test GO
    CREATE TABLE test.users (name string, age int) GO";

    db.run(&sql, &mut tr);

    let sql = "DECLARE @i int SET @i = 8192
      WHILE @i > 0
      BEGIN
        INSERT INTO test.users(name,age) VALUES ('Alice', 1000)
        SET @i -= 1
      END";

    db.run(&sql, &mut tr);

    let mut results = Vec::new();
    for _outer in 0..100 {
        let start = std::time::Instant::now();
        for _i in 0..10 {
            let ut = db.table("test", "users");
            assert!(data_kind(ut.info.typ[1]) == DataKind::Int);
            assert!(data_size(ut.info.typ[1]) == 8);
            let col_off = ut.info.off[1];
            let mut total = 0;
            for (pp, off) in ut.scan(&db) {
                let p = &pp.borrow();
                // let a = ut.access(p, off); total += a.int(1);
                total += util::iget(&p.data, off + col_off, 8);
            }
            assert_eq!(total, 8192000);
        }
        results.push(start.elapsed().as_micros() as u64);
    }
    print_results("rustdb_direct_test", results);
}

#[cfg(test)]
pub fn print_results(name: &str, mut results: Vec<u64>) {
    results.sort();
    let n = results.len() / 10;
    let results = &results[0..n];
    let mut total = 0;
    for result in results {
        total += result;
    }
    println!(
        "{} average time={} sorted results={:?}",
        name,
        total / (n as u64),
        results
    );
}