Skip to content

Commit

Permalink
Sqlite database tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alexsanjoseph committed Mar 20, 2022
1 parent bd9c025 commit 5ff381c
Show file tree
Hide file tree
Showing 3 changed files with 286 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"cSpell.words": [
"imdb"
"imdb",
"sqdb"
]
}
158 changes: 158 additions & 0 deletions riemann/sqlite_database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package riemann

import (
"database/sql"
"fmt"
"log"

_ "github.com/mattn/go-sqlite3"
)

type SqliteDivisorDb struct {
DBPath string
db *sql.DB
}

func (sqdb SqliteDivisorDb) Initialize() {

db, err := sql.Open("sqlite3", sqdb.DBPath)
if err != nil {
log.Fatal(err)
}
sqlStmt := `
CREATE TABLE RiemannDivisorSums (
n UNSIGNED BIG INT CONSTRAINT divisor_sum_pk PRIMARY KEY,
divisor_sum UNSIGNED BIG INT,
witness_value REAL
);
`
_, err = db.Exec(sqlStmt)
if err != nil {
panic(err)
}
db.Close()
}

func (sqdb *SqliteDivisorDb) ensureInit() {
db, err := sql.Open("sqlite3", sqdb.DBPath)
if err != nil {
log.Fatal(err)
}
sqdb.db = db
}

func (sqdb SqliteDivisorDb) Load() []RiemannDivisorSum {
sqdb.ensureInit()
defer sqdb.db.Close()
sqlStmt := `
SELECT n, divisor_sum, witness_value
FROM RiemannDivisorSums
ORDER BY n asc;
`
rows, err := sqdb.db.Query(sqlStmt)
if err != nil {
panic(err)
}
defer rows.Close()
output := []RiemannDivisorSum{}
for rows.Next() {
var n, divisorSum int64
var witnessValue float64
err = rows.Scan(&n, &divisorSum, &witnessValue)
if err != nil {
log.Fatal(err)
}
output = append(output, RiemannDivisorSum{
N: n,
DivisorSum: divisorSum,
WitnessValue: witnessValue,
})
}
return output
}

func (sqdb SqliteDivisorDb) Upsert(rds []RiemannDivisorSum) {
sqdb.ensureInit()
defer sqdb.db.Close()

tx, err := sqdb.db.Begin()
if err != nil {
log.Fatal(err)
}
sqlStmt, err := tx.Prepare(`
INSERT INTO
RiemannDivisorSums(n, divisor_sum, witness_value)
VALUES(?, ?, ?)
ON CONFLICT(n) DO UPDATE SET
divisor_sum=excluded.divisor_sum,
witness_value=excluded.witness_value;
;
`)
if err != nil {
log.Fatal(err)
}
defer sqlStmt.Close()
for _, value := range rds {
_, err := sqlStmt.Exec(
fmt.Sprintf("%d", value.N),
fmt.Sprintf("%d", value.DivisorSum),
fmt.Sprintf("%f", value.WitnessValue),
)
if err != nil {
log.Fatal(err)
}
}
tx.Commit()
sqdb.db.Close()
}

func (sqdb SqliteDivisorDb) Summarize() SummaryStats {
sqdb.ensureInit()
defer sqdb.db.Close()

largestNStms := `
SELECT *
FROM RiemannDivisorSums
ORDER BY n DESC
LIMIT 1;
`
row := sqdb.db.QueryRow(largestNStms)
var n, divisorSum int64
var witnessValue float64
err := row.Scan(&n, &divisorSum, &witnessValue)
if err != nil {
return SummaryStats{
LargestWitnessValue: RiemannDivisorSum{},
LargestComputedN: RiemannDivisorSum{},
}
}

largest_computed_n := RiemannDivisorSum{
N: n,
DivisorSum: divisorSum,
WitnessValue: witnessValue,
}

largestWitnessStmt := `
SELECT *
FROM RiemannDivisorSums
ORDER BY witness_value DESC
LIMIT 1;
`
row = sqdb.db.QueryRow(largestWitnessStmt)
err = row.Scan(&n, &divisorSum, &witnessValue)
if err != nil {
panic(err)
}
largest_witness_value := RiemannDivisorSum{
N: n,
DivisorSum: divisorSum,
WitnessValue: witnessValue,
}

return SummaryStats{
LargestWitnessValue: largest_witness_value,
LargestComputedN: largest_computed_n,
}

}
126 changes: 126 additions & 0 deletions riemann/sqlite_database_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package riemann_test

import (
"os"
"sort"

"github.com/alexsanjoseph/riemann-divisor-sum-go/riemann"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

const DBPath = "test.sqlite"

var _ = BeforeEach(func() {
os.Remove(DBPath)
var db = riemann.DivisorDb(&riemann.SqliteDivisorDb{DBPath: DBPath})
db.Initialize()
})

var _ = AfterEach(func() {
os.Remove(DBPath)
})

var _ = Describe("Sqlite Database Tests", func() {

It("is initially empty", func() {
var db = riemann.DivisorDb(&riemann.SqliteDivisorDb{DBPath: DBPath})
loadedData := db.Load()
Expect(len(loadedData)).To(Equal(0))
})

It("Upserts correctly", func() {
var db = riemann.DivisorDb(&riemann.SqliteDivisorDb{DBPath: DBPath})
records := []riemann.RiemannDivisorSum{
{N: 1, DivisorSum: 1, WitnessValue: 1},
{N: 2, DivisorSum: 2, WitnessValue: 2},
}

By("upserting fine from empty", func() {
db.Upsert(records)
loadedData := db.Load()
sort.Slice(loadedData, func(p, q int) bool {
return loadedData[p].N < loadedData[q].N
})
Expect(loadedData).To(Equal(records))
})

By("upserting fine from non-empty", func() {
newRecords := []riemann.RiemannDivisorSum{
{N: 3, DivisorSum: 3, WitnessValue: 3},
{N: 4, DivisorSum: 4, WitnessValue: 4},
}
db.Upsert(newRecords)
loadedData := db.Load()
sort.Slice(loadedData, func(p, q int) bool {
return loadedData[p].N < loadedData[q].N
})
Expect(loadedData).To(Equal(append(records, newRecords...)))
})

By("overriding existing docs when upserted", func() {
newRecords := []riemann.RiemannDivisorSum{
{N: 3, DivisorSum: 3, WitnessValue: 10},
{N: 5, DivisorSum: 5, WitnessValue: 5},
}
expectedNewRecords := []riemann.RiemannDivisorSum{
{N: 3, DivisorSum: 3, WitnessValue: 10},
{N: 4, DivisorSum: 4, WitnessValue: 4},
{N: 5, DivisorSum: 5, WitnessValue: 5},
}
db.Upsert(newRecords)
loadedData := db.Load()
sort.Slice(loadedData, func(p, q int) bool {
return loadedData[p].N < loadedData[q].N
})
Expect(loadedData).To(Equal(append(records, expectedNewRecords...)))
})

})

It("Summarizes", func() {
var db = riemann.DivisorDb(&riemann.SqliteDivisorDb{DBPath: DBPath})
By("correctly summarizing empty data", func() {
summaryData := db.Summarize()
expectedSummaryData := riemann.SummaryStats{
LargestWitnessValue: riemann.RiemannDivisorSum{},
LargestComputedN: riemann.RiemannDivisorSum{},
}
Expect(summaryData).To(Equal(expectedSummaryData))
})

By("correctly summarizing non-empty data", func() {
records := []riemann.RiemannDivisorSum{
{N: 1, DivisorSum: 1, WitnessValue: 10},
{N: 2, DivisorSum: 2, WitnessValue: 20},
{N: 3, DivisorSum: 2, WitnessValue: 3},
}
db.Upsert(records)
summaryData := db.Summarize()
expectedSummaryData := riemann.SummaryStats{
LargestWitnessValue: riemann.RiemannDivisorSum{N: 2, DivisorSum: 2, WitnessValue: 20},
LargestComputedN: riemann.RiemannDivisorSum{N: 3, DivisorSum: 2, WitnessValue: 3},
}
Expect(summaryData).To(Equal(expectedSummaryData))
})

})

It("Summarizes for float values", func() {
var db = riemann.DivisorDb(&riemann.SqliteDivisorDb{DBPath: DBPath})
By("correctly summarizing non-empty data", func() {
records := []riemann.RiemannDivisorSum{
{N: 10092, DivisorSum: 24388, WitnessValue: 1.088},
{N: 10080, DivisorSum: 39000, WitnessValue: 1.788},
}
db.Upsert(records)
summaryData := db.Summarize()
expectedSummaryData := riemann.SummaryStats{
LargestWitnessValue: riemann.RiemannDivisorSum{N: 10080, DivisorSum: 39000, WitnessValue: 1.788},
LargestComputedN: riemann.RiemannDivisorSum{N: 10092, DivisorSum: 24388, WitnessValue: 1.088},
}
Expect(summaryData).To(Equal(expectedSummaryData))
})
})

})

0 comments on commit 5ff381c

Please sign in to comment.