-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdb.du
130 lines (113 loc) · 3.71 KB
/
db.du
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
import Sqlite;
import System;
const
schemaCreateQuery = "CREATE TABLE IF NOT EXISTS db (field TEXT PRIMARY KEY, value TEXT, expiresAt INTEGER)",
getItemQuery = "SELECT value FROM db WHERE field = ? AND expiresAt == 0 OR expiresAt > ?",
setItemQuery = "INSERT OR REPLACE INTO db (field, value, expiresAt) VALUES (?, ?, ?)",
deleteItemQuery = "DELETE FROM db WHERE field = ?",
containsItemQuery = "SELECT 1 FROM db WHERE field = ? AND expiresAt >= ? OR expiresAt == 0",
selectKeysQuery = "SELECT field FROM db WHERE expiresAt >= ? OR expiresAt == 0",
selectValuesQuery = "SELECT value FROM db WHERE expiresAt >= ? OR expiresAt == 0",
selectItemsQuery = "SELECT field, value FROM db WHERE expiresAt >= ? OR expiresAt == 0",
itemCountQuery = "SELECT COUNT(*) FROM db WHERE expiresAt >= ? OR expiresAt == 0",
deleteExpiredQuery = "DELETE * FROM db WHERE expiresAt < ? OR expiresAt != 0";
/**
* DB is a key / value store that can be either in-memory
* or persisted to disk.
*/
class DB {
init(filename="") {
if (filename != "") {
this.db = Sqlite.connect(filename).unwrap();
} else {
this.db = Sqlite.connect(":memory:").unwrap();
}
this.startUp();
}
/**
* startUp makes sure that table the data is stored in exists.
*/
private startUp() {
this.db.execute(schemaCreateQuery).unwrap();
}
/**
* close closes the db connection.
*/
close() {
this.db.close();
}
/**
* get retrieves the value for the given key. If the key doesn't
* exist, an empty string is returned.
*/
get(key) {
const now = System.time();
const row = this.db.execute(getItemQuery, [key, now]).unwrap();
return row.len() == 0 ? "" : row[0][0];
}
/**
* set sets the given key to the value provided. If the key exists, the value
* is updated.
*/
set(key, value, ttl=0) {
var expiresAt = 0;
if (ttl > 0) {
expiresAt += System.time() + ttl;
}
this.db.execute(setItemQuery, [key, value, expiresAt]).unwrap();
}
/**
* del deletes the item identified by the given key
* from the db.
*/
del(key) {
return this.db.execute(deleteItemQuery, [key]).unwrap();
}
/**
* contains checks if the given key exists in the db.
*/
contains(key) {
const now = System.time();
const res = this.db.execute(containsItemQuery, [key, now]).unwrap();
return res.len() == 0 ? false : true;
}
/**
* keys returns a list of all keys in the db.
*/
keys() {
const now = System.time();
const rows = this.db.execute(selectKeysQuery, [now]).unwrap();
return rows.len() != 0 ? rows.map(def(r) => r[0]) : [];
}
/**
* values returns a list of all values in the db.
*/
values() {
const now = System.time();
const rows = this.db.execute(selectValuesQuery, [now]).unwrap();
return rows.len() != 0 ? rows.map(def(r) => r[0]) : [];
}
/**
* items returns all items in the db.
*/
items() {
const now = System.time();
const rows = this.db.execute(selectItemsQuery, [now]).unwrap();
return rows;
}
/**
* len returns the number of keys in the db.
*/
len() {
const now = System.time();
const rows = this.db.execute(itemCountQuery, [now]).unwrap();
return rows[0][0];
}
/**
* purgeExpired removes all expired items from the store.
*/
purgeExpired() {
const now = System.time();
return this.db.execute(deleteExpiredQuery, [now]).unwrap();
}
}