Repository: tursodatabase/limbo (language: rust)

Issue:
wrong count() result if the column specified contains a NULL
CREATE TABLE IF NOT EXISTS counter (
        id INTEGER PRIMARY KEY,
        t TEXT,
        r REAL,
        i INTEGER,
        b BLOB
    );

INSERT INTO counter (t, r, i, b) VALUES ('ONE', 1, 1, 'ONE');
INSERT INTO counter (t, r, i, b) VALUES ('TWO', 2, 2, 'TWO');
INSERT INTO counter (t, r, i, b) VALUES ('THREE', 3, 3, 'THREE');
INSERT INTO counter (t, r, i, b) VALUES ('ONE', 1, 1, 'ONE');
INSERT INTO counter (t, r, i, b) VALUES ('TWO', 2, 2, 'TWO');
INSERT INTO counter (t, r, i, b) VALUES ('THREE', 3, 3, 'THREE');
INSERT INTO counter (t, r, i, b) VALUES ('ONE', 1, 1, 'ONE');
INSERT INTO counter (t, r, i, b) VALUES ('TWO', 2, 2, 'TWO');
INSERT INTO counter (t, r, i, b) VALUES ('THREE', 3, 3, 'THREE');
INSERT INTO counter (t, r, i, b) VALUES (NULL, NULL, NULL, NULL);

SQLite version 3.49.1 2025-02-18 13:38:58
Enter ".help" for usage hints.
sqlite> select count(i) from counter;
9

Limbo v0.0.15
Enter ".help" for usage hints.
limbo> select count(i) from counter;
10

wrong count() result if the column specified contains a NULL
CREATE TABLE IF NOT EXISTS counter (
        id INTEGER PRIMARY KEY,
        t TEXT,
        r REAL,
        i INTEGER,
        b BLOB
    );

INSERT INTO counter (t, r, i, b) VALUES ('ONE', 1, 1, 'ONE');
INSERT INTO counter (t, r, i, b) VALUES ('TWO', 2, 2, 'TWO');
INSERT INTO counter (t, r, i, b) VALUES ('THREE', 3, 3, 'THREE');
INSERT INTO counter (t, r, i, b) VALUES ('ONE', 1, 1, 'ONE');
INSERT INTO counter (t, r, i, b) VALUES ('TWO', 2, 2, 'TWO');
INSERT INTO counter (t, r, i, b) VALUES ('THREE', 3, 3, 'THREE');
INSERT INTO counter (t, r, i, b) VALUES ('ONE', 1, 1, 'ONE');
INSERT INTO counter (t, r, i, b) VALUES ('TWO', 2, 2, 'TWO');
INSERT INTO counter (t, r, i, b) VALUES ('THREE', 3, 3, 'THREE');
INSERT INTO counter (t, r, i, b) VALUES (NULL, NULL, NULL, NULL);

SQLite version 3.49.1 2025-02-18 13:38:58
Enter ".help" for usage hints.
sqlite> select count(i) from counter;
9

Limbo v0.0.15
Enter ".help" for usage hints.
limbo> select count(i) from counter;
10



Discussion / hints:

Fix patch:
diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs
index 8187c1487..38b2092db 100644
--- a/core/vdbe/mod.rs
+++ b/core/vdbe/mod.rs
@@ -1722,6 +1722,7 @@ impl Program {
                             *acc += col;
                         }
                         AggFunc::Count | AggFunc::Count0 => {
+                            let col = state.registers[*col].clone();
                             if matches!(&state.registers[*acc_reg], OwnedValue::Null) {
                                 state.registers[*acc_reg] = OwnedValue::Agg(Box::new(
                                     AggContext::Count(OwnedValue::Integer(0)),
@@ -1734,7 +1735,12 @@ impl Program {
                             let AggContext::Count(count) = agg.borrow_mut() else {
                                 unreachable!();
                             };
-                            *count += 1;
+
+                            if (matches!(func, AggFunc::Count) && matches!(col, OwnedValue::Null))
+                                == false
+                            {
+                                *count += 1;
+                            };
                         }
                         AggFunc::Max => {
                             let col = state.registers[*col].clone();


Test patch: