aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZach Berwaldt <zberwaldt@tutamail.com>2024-03-16 10:48:52 -0400
committerZach Berwaldt <zberwaldt@tutamail.com>2024-03-16 11:25:29 -0400
commitb32419dfe996fbc9731b48ba528bae67535f4839 (patch)
tree9704a77e53968fe1c6094fa8eb9714b59ed59b8d
parentfe8f79b7afc10040d653b5d7f7016dc93df1eebd (diff)
clean up database scripts, start readmes.
-rw-r--r--README.md17
-rw-r--r--db/README.md3
-rw-r--r--db/scripts/init.sh9
-rw-r--r--db/scripts/water_init.sql86
-rw-r--r--db/sql/seed.sql5
-rw-r--r--db/sql/tables.sql39
-rw-r--r--db/sql/triggers.sql11
-rw-r--r--db/sql/views.sql27
8 files changed, 111 insertions, 86 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6c0b743
--- /dev/null
+++ b/README.md
@@ -0,0 +1,17 @@
1# Water
2
3Water is a simple tracking application for the amount of water you and
4others drink. Complete with simple data visualizations for the daily consumptions,
5plus over the last seven days
6
7## Stack
8
9This project uses the following technologies:
10
11- [Svelte][fe] for the frontend
12- [Gin][api] for the backend
13- [Sqlite3][db] for the database
14
15[fe]: https://svelte.dev/
16[api]: https://gin-gonic.com/
17[db]: https://www.sqlite.org/index.html \ No newline at end of file
diff --git a/db/README.md b/db/README.md
new file mode 100644
index 0000000..f36e555
--- /dev/null
+++ b/db/README.md
@@ -0,0 +1,3 @@
1# The Database
2
3This document describes how to set up the database for your instance of the water application. \ No newline at end of file
diff --git a/db/scripts/init.sh b/db/scripts/init.sh
new file mode 100644
index 0000000..e55292b
--- /dev/null
+++ b/db/scripts/init.sh
@@ -0,0 +1,9 @@
1sqlite3 $DB_PATH < ../sql/tables.sql
2
3insert_user() {
4read -p "Enter a username: " username
5read -sp
6 }
7
8echo "Before continuing you must create users. The reset of the schema depends on them"
9
diff --git a/db/scripts/water_init.sql b/db/scripts/water_init.sql
deleted file mode 100644
index 1099d09..0000000
--- a/db/scripts/water_init.sql
+++ /dev/null
@@ -1,86 +0,0 @@
1-- user table for users.
2CREATE TABLE IF NOT EXISTS Users (
3 id INTEGER PRIMARY KEY,
4 password TEXT UNIQUE NOT NULL,
5 uuid TEXT UNIQUE NOT NULL,
6 name TEXT UNIQUE NOT NULL
7);
8
9-- statistics table for users to log their consumption
10CREATE TABLE IF NOT EXISTS Statistics (
11 id INTEGER PRIMARY KEY,
12 date DATETIME NOT NULL,
13 user_id INT NOT NULL,
14 quantity INT
15);
16
17-- preferences table for a user.
18CREATE TABLE IF NOT EXISTS Preferences (
19 id INTEGER PRIMARY KEY,
20 color TEXT NOT NULL DEFAULT "#000000",
21 user_id INT UNIQUE NOT NULL,
22 size_id INT NOT NULL DEFAULT 1,
23 FOREIGN KEY(user_id) REFERENCES Users(id) ON DELETE CASCADE,
24 FOREIGN KEY(size_id) REFERENCES Sizes(id)
25);
26
27-- lookup table for sizes.
28CREATE TABLE IF NOT EXISTS Sizes (
29 id INTEGER PRIMARY KEY,
30 size INT NOT NULL,
31 unit TEXT DEFAULT "oz"
32);
33
34CREATE TABLE IF NOT EXISTS APIToken (
35 id INTEGER PRIMARY KEY,
36 token TEXT NOT NULL,
37 user_id INTEGER NOT NULL,
38 FOREIGN KEY(user_id) REFERENCES Users(id) ON DELETE CASCADE
39);
40
41-- create default sizes for sizes lookup table.
42INSERT OR IGNORE INTO Sizes (id, size) VALUES (1, 8), (2, 16), (3, 24), (4, 32), (5, 40), (6, 48);
43
44-- create default preferences.
45INSERT OR IGNORE INTO Preferences (user_id) VALUES (1), (2);
46
47CREATE TRIGGER IF NOT EXISTS enforce_size_id
48BEFORE INSERT ON Preferences
49BEGIN
50 SELECT
51 CASE
52 WHEN (
53 SELECT COUNT(*) FROM Sizes WHERE id = new.size_id
54 ) = 0
55 THEN RAISE(ABORT, 'Size does not exist')
56 END;
57END;
58
59--
60CREATE VIEW IF NOT EXISTS aggregated_stats AS
61 SELECT u.uuid, SUM(s.quantity * s.size) from Statistics s INNER JOIN Users u ON u.id = s.user_id INNER JOIN Preferences p ON p.user_id = u.id INNER JOIN Size s ON s.id = p.size_id;
62
63CREATE VIEW IF NOT EXISTS `DailyUserStatistics` AS
64SELECT users.name, IFNULL(SUM(statistics.quantity), 0) as total, preferences.color as color
65FROM users
66LEFT JOIN statistics ON users.id = statistics.user_id AND DATE(statistics.date) = DATE('now', '-1 day')
67LEFT JOIN preferences ON users.id = preferences.user_id
68GROUP BY users.name;
69
70
71CREATE VIEW IF NOT EXISTS `WeeklyStatisticsView` AS
72 WITH DateSequence(Dates) AS
73 (
74 SELECT Date(CURRENT_DATE, '-7 day')
75 UNION ALL
76 SELECT Date(Dates, '+1 day')
77 FROM DateSequence
78 WHERE Date(Dates, '+1 day') < Date(CURRENT_DATE)
79 )
80SELECT DateSequence.Dates as 'date',
81 IFNULL(SUM(statistics.quantity), 0) AS 'total'
82FROM DateSequence
83LEFT JOIN statistics
84ON Date(statistics.date) = DateSequence.Dates
85GROUP BY DateSequence.Dates
86ORDER BY DateSequence.Dates; \ No newline at end of file
diff --git a/db/sql/seed.sql b/db/sql/seed.sql
new file mode 100644
index 0000000..41d6e46
--- /dev/null
+++ b/db/sql/seed.sql
@@ -0,0 +1,5 @@
1-- create default sizes for sizes lookup table.
2INSERT OR IGNORE INTO Sizes (id, size) VALUES (1, 8), (2, 16), (3, 24), (4, 32), (5, 40), (6, 48);
3
4-- create default preferences.
5INSERT OR IGNORE INTO Preferences (user_id) VALUES (1), (2);
diff --git a/db/sql/tables.sql b/db/sql/tables.sql
new file mode 100644
index 0000000..0fbfef8
--- /dev/null
+++ b/db/sql/tables.sql
@@ -0,0 +1,39 @@
1-- user table for users.
2CREATE TABLE IF NOT EXISTS Users (
3 id INTEGER PRIMARY KEY,
4 password TEXT UNIQUE NOT NULL,
5 uuid TEXT UNIQUE NOT NULL,
6 name TEXT UNIQUE NOT NULL
7);
8
9-- statistics table for users to log their consumption
10CREATE TABLE IF NOT EXISTS Statistics (
11 id INTEGER PRIMARY KEY,
12 date DATETIME NOT NULL,
13 user_id INT NOT NULL,
14 quantity INT
15);
16
17-- preferences table for a user.
18CREATE TABLE IF NOT EXISTS Preferences (
19 id INTEGER PRIMARY KEY,
20 color TEXT NOT NULL DEFAULT "#000000",
21 user_id INT UNIQUE NOT NULL,
22 size_id INT NOT NULL DEFAULT 1,
23 FOREIGN KEY(user_id) REFERENCES Users(id) ON DELETE CASCADE,
24 FOREIGN KEY(size_id) REFERENCES Sizes(id)
25);
26
27-- lookup table for sizes.
28CREATE TABLE IF NOT EXISTS Sizes (
29 id INTEGER PRIMARY KEY,
30 size INT NOT NULL,
31 unit TEXT DEFAULT "oz"
32);
33
34CREATE TABLE IF NOT EXISTS APIToken (
35 id INTEGER PRIMARY KEY,
36 token TEXT NOT NULL,
37 user_id INTEGER NOT NULL,
38 FOREIGN KEY(user_id) REFERENCES Users(id) ON DELETE CASCADE
39); \ No newline at end of file
diff --git a/db/sql/triggers.sql b/db/sql/triggers.sql
new file mode 100644
index 0000000..3827642
--- /dev/null
+++ b/db/sql/triggers.sql
@@ -0,0 +1,11 @@
1CREATE TRIGGER IF NOT EXISTS enforce_size_id
2BEFORE INSERT ON Preferences
3BEGIN
4 SELECT
5 CASE
6 WHEN (
7 SELECT COUNT(*) FROM Sizes WHERE id = new.size_id
8 ) = 0
9 THEN RAISE(ABORT, 'Size does not exist')
10 END;
11END;
diff --git a/db/sql/views.sql b/db/sql/views.sql
new file mode 100644
index 0000000..c56286d
--- /dev/null
+++ b/db/sql/views.sql
@@ -0,0 +1,27 @@
1CREATE VIEW IF NOT EXISTS aggregated_stats AS
2 SELECT u.uuid, SUM(s.quantity * s.size) from Statistics s INNER JOIN Users u ON u.id = s.user_id INNER JOIN Preferences p ON p.user_id = u.id INNER JOIN Size s ON s.id = p.size_id;
3
4CREATE VIEW IF NOT EXISTS `DailyUserStatistics` AS
5SELECT users.name, IFNULL(SUM(statistics.quantity), 0) as total, preferences.color as color
6FROM users
7LEFT JOIN statistics ON users.id = statistics.user_id AND DATE(statistics.date) = DATE('now', '-1 day')
8LEFT JOIN preferences ON users.id = preferences.user_id
9GROUP BY users.name;
10
11
12CREATE VIEW IF NOT EXISTS `WeeklyStatisticsView` AS
13 WITH DateSequence(Dates) AS
14 (
15 SELECT Date(CURRENT_DATE, '-7 day')
16 UNION ALL
17 SELECT Date(Dates, '+1 day')
18 FROM DateSequence
19 WHERE Date(Dates, '+1 day') < Date(CURRENT_DATE)
20 )
21SELECT DateSequence.Dates as 'date',
22 IFNULL(SUM(statistics.quantity), 0) AS 'total'
23FROM DateSequence
24LEFT JOIN statistics
25ON Date(statistics.date) = DateSequence.Dates
26GROUP BY DateSequence.Dates
27ORDER BY DateSequence.Dates; \ No newline at end of file