Skip to content

Commit 9d42bee

Browse files
committed
wip
1 parent b5a039f commit 9d42bee

File tree

2 files changed

+78
-7
lines changed

2 files changed

+78
-7
lines changed

README.md

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,73 @@
22

33
A Graph Database for Julia, built on top of [SQLite.jl](https://github.com/JuliaDatabases/SQLite.jl).
44

5+
## Quickstart
6+
7+
- *Nodes* must have "properties", even if `nothing`.
8+
- *Edges* must have "properties", even if `nothing`.
9+
10+
11+
### Creating a Graph Database
12+
13+
```julia
14+
using SQLiteGraph
15+
16+
db = DB()
17+
# SimpleGraphDB(":memory:") (0 nodes, 0 edges)
18+
```
19+
20+
### Adding Nodes
21+
22+
```julia
23+
db[1] = (x=1, y=2)
24+
# properties must be `JSON3.write`-able (saved in the SQLite database as TEXT)
25+
db[2] = (x=1, y=10)
26+
27+
db[1]
28+
# "{\"x\":1,\"y\":2}"
29+
```
30+
31+
### Adding Edges
32+
33+
```julia
34+
db[1,2] = (a=1, b=2)
35+
36+
db[1,2]
37+
# "{\"a\":1,\"b\":2}"
38+
```
39+
40+
### `ReadAs`
41+
42+
- You can wrap a `DB` with `ReadAs` to enforce how you want the `TEXT` to be `JSON3.read`:
43+
44+
```julia
45+
rdb = ReadAs(db, Dict{String, Int})
46+
# ReadAs{Dict{String, Int64}}: SimpleGraphDB(":memory:") (2 nodes, 1 edges)
47+
48+
rdb[1]
49+
# Dict{String, Int64} with 2 entries:
50+
# "x" => 1
51+
# "y" => 2
52+
53+
rdb[1,2]
54+
# Dict{String, Int64} with 2 entries:
55+
# "b" => 2
56+
# "a" => 1
57+
```
58+
59+
560

661
## Attribution
762

8-
SQLiteGraph is **Strongly** influenced (much has been copied verbatim) by [https://github.com/dpapathanasiou/simple-graph](https://github.com/dpapathanasiou/simple-graph).
63+
SQLiteGraph is **STRONGLY** influenced (much has been copied verbatim) from [https://github.com/dpapathanasiou/simple-graph](https://github.com/dpapathanasiou/simple-graph).
64+
65+
The differences here are minor, opinionated changes made by `@joshday`:
966

10-
The differences here are minor, opinionated changes made by `@joshday`.
67+
- Node IDs are `Int`: 1, 2, 3...
68+
- Both `nodes` and `edges` tables have field `props`
1169

1270
## TODOs
1371

1472
- Prepare SQL into compiled `SQLite.Stmt`s.
73+
- querying
74+
- traverse

src/SQLiteGraph.jl

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using SQLite: SQLite
44
import DBInterface: execute
55
using JSON3: JSON3
66

7-
export DB, Node, Edge
7+
export DB, ReadAs
88

99
#-----------------------------------------------------------------------------# utils
1010
read_sql(fn::String) = read(joinpath(@__DIR__, "sql", fn), String)
@@ -71,6 +71,7 @@ n_nodes(db::DB) = single_result_execute(db, "SELECT Count(*) FROM nodes")
7171
n_edges(db::DB) = single_result_execute(db, "SELECT Count(*) FROM edges")
7272

7373
Base.length(db::DB) = n_nodes(db)
74+
Base.size(db::DB) = (n_nodes(db), n_edges(db))
7475
Base.lastindex(db::DB) = length(db)
7576

7677
init!(db::DB, n) = (foreach(id -> setindex!(db, nothing, id), 1:n); db)
@@ -81,11 +82,12 @@ struct ReadAs{T}
8182
db::DB
8283
end
8384
ReadAs(db::DB, T::DataType=Dict{String,Any}) = ReadAs{T}(db)
85+
Base.show(io::IO, r::ReadAs{T}) where {T} = (print(io, "ReadAs{$T}: "); print(io, r.db))
8486
Base.setindex!(r::ReadAs, args...) = setindex!(r.db, args...)
85-
Base.getindex(r::ReadAs{T}, args...) where {T} = (res=r[args...]; isnothing(res) ? res : JSON3.read(res, T))
87+
Base.getindex(r::ReadAs{T}, args...) where {T} = (res=r.db[args...]; isnothing(res) ? res : JSON3.read(res, T))
88+
Base.deleteat!(r::ReadAs, args...) = deleteat!(r.db, args...)
8689

87-
88-
#-----------------------------------------------------------------------------# set/get node(s)
90+
#-----------------------------------------------------------------------------# nodes
8991
function Base.setindex!(db::DB, props, id::Integer)
9092
execute(db, "INSERT INTO nodes VALUES(?, json(?))", (id, JSON3.write(props)))
9193
db
@@ -94,14 +96,23 @@ function Base.getindex(db::DB, id::Integer)
9496
res = single_result_execute(db, "SELECT props FROM nodes WHERE id = ?", (id,))
9597
isnothing(res) ? throw(BoundsError(db, id)) : res
9698
end
99+
function Base.deleteat!(db::DB, id::Integer)
100+
execute(db, "DELETE FROM nodes WHERE id = ?", (id,))
101+
execute(db, "DELETE FROM edges WHERE source = ? OR target = ?", (id, id))
102+
db
103+
end
97104

98-
#-----------------------------------------------------------------------------# set/get edge(s)
105+
#-----------------------------------------------------------------------------# edges
99106
function Base.setindex!(db::DB, props, i::Integer, j::Integer)
100107
execute(db, "INSERT INTO edges VALUES(?, ?, json(?))", (i, j, JSON3.write(props)))
101108
db
102109
end
103110
function Base.getindex(db::DB, i::Integer, j::Integer)
104111
single_result_execute(db, "SELECT props FROM edges WHERE source = ? AND target = ? ", (i,j))
105112
end
113+
function Base.deleteat!(db::DB, i::Integer, j::Integer)
114+
execute(db, "DELETE FROM edges WHERE source = ? AND target = ?", (i, j))
115+
db
116+
end
106117

107118
end

0 commit comments

Comments
 (0)