Skip to content
This repository has been archived by the owner on Oct 17, 2021. It is now read-only.

Commit

Permalink
[WIP] Add foreign key actions and delete! and select_all (#7)
Browse files Browse the repository at this point in the history
* Add initial foreign key actions

* Add delete! for redis and relational

* add select_all

* Improve documentation

* Fix bug with pk deleting

* Improve documentation

* Bump version
  • Loading branch information
lucianolorenti committed Mar 5, 2020
1 parent ab895cf commit 6568129
Show file tree
Hide file tree
Showing 13 changed files with 532 additions and 170 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "StructDatabaseMapping"
uuid = "66daddfc-c305-4fd9-8f84-fb59daccc546"
authors = ["Luciano Rolando Lorenti <lucianolorenti@gmail.com>"]
version = "0.2.0"
version = "0.3.0"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand Down
8 changes: 7 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
using Documenter, StructDatabaseMapping

makedocs(sitename="Struct Database Mapping",
pages = ["example.md"])
format = Documenter.HTML(prettyurls = false),
modules = [StructDatabaseMapping],
pages = [
"Home" => "index.md",
"Api" => "api.md",
"Example"=>"example.md"]
)

deploydocs(
repo="github.com/lucianolorenti/StructDatabaseMapping.jl.git")
10 changes: 10 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Api
```@docs
select_one
select_all
update!
delete!
drop_table!
clean_table!
exists
```
8 changes: 8 additions & 0 deletions docs/src/example.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ mapper = DBMapper(creator)
register!(mapper, Author)
register!(mapper, Book)
configure_relation(mapper, Book, :author, on_delete=Cascade())
@test haskey(mapper.tables, Author)
@test haskey(mapper.tables, Book)
Expand Down Expand Up @@ -134,6 +136,12 @@ book = select_one(mapper, Book, id="super_string_id")
println(book)
```

# Delete
```@example code_1
book = select_one(mapper, Book, id="super_string_id")
delete!(mapper, book)
```

# Removing tables
```@example code_1
drop_table!(mapper, Author)
Expand Down
1 change: 1 addition & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Index
136 changes: 98 additions & 38 deletions src/NonRelational/Redis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function insert!(mapper::DBMapper, ::Type{Redis.RedisConnection}, elem::T) wher
end
id = redis_id(T, getid(elem, mapper))
result = Redis.hmset(conn, id, marshal(mapper, elem))
release_connection(mapper.pool, conn)
release_connection(mapper.pool, conn)
end

function select_one(mapper::DBMapper, ::Type{Redis.RedisConnection}, T::Type{<:Model}; kwargs...)
Expand All @@ -20,7 +20,7 @@ function select_one(mapper::DBMapper, ::Type{Redis.RedisConnection}, T::Type{<:M
id = params[id_field]
conn = get_connection(mapper.pool)
result = Redis.hgetall(conn, redis_id(T, id))
release_connection(mapper.pool, conn)
release_connection(mapper.pool, conn)
if isempty(result)
return nothing
else
Expand All @@ -36,11 +36,11 @@ function clean_table!(mapper::DBMapper, ::Type{Redis.RedisConnection}, elem::Typ
(cursor, results) = Redis.scan(conn, cursor, "match", redis_wildcard(T))
Redis.unlik(conn, keys...)
end
release_connection(mapper.pool, conn)
release_connection(mapper.pool, conn)
end

function drop_table!(::DBMapper, ::Type{Redis.RedisConnection}, elem::Type{T}) where T<:Model

end
function update!(mapper::DBMapper, ::Type{Redis.RedisConnection}, elem::T; fields::Array{Symbol}=Symbol[]) where T<:Model
id = getid(elem, mapper)
Expand All @@ -49,59 +49,119 @@ function update!(mapper::DBMapper, ::Type{Redis.RedisConnection}, elem::T; field
end
data = marshal(mapper, elem)
if length(fields) > 0
for f in keys(data)
for f in keys(data)
if !(f in fields)
pop!(data, f)
pop!(data, f)
end
end
end
id = redis_id(T, id)
conn = get_connection(mapper.pool)
conn = get_connection(mapper.pool)
result = Redis.hmset(conn, id, data)
release_connection(mapper.pool, conn)
release_connection(mapper.pool, conn)
end
function exists(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<:Model}; kwargs...)

function extract_id_from_kwargs(mapper::DBMapper, T::Type{<:Model}; kwargs...)
id_f = idfield(mapper, T)
params = Dict(kwargs...)
id = nothing
if haskey(params, id_f)
id = redis_id(T, pop!(params, id_f))
end
id = redis_id(T, pop!(params, id_f))
end
return (id, params)
end

function select_by_key_and_params(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<:Model}, pk, params)
conn = get_connection(mapper.pool)
params_key = collect(keys(params))
elem_values = Redis.hmget(conn, pk, params_key...)
release_connection(mapper.pool, conn)
return unmarshal(mapper, T, Dict(zip(params_key, elem_values)); partial=true)
end

function iterate_all(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<:Model}, params, f)
conn = get_connection(mapper.pool)
cursor = -1
params_key = collect(keys(params))
while cursor != 0
(cursor, results) = Redis.scan(conn, cursor == -1 ? 0 : cursor, "match", redis_wildcard(T))
for elem_key in results
elem_values = Redis.hmget(conn, elem_key, params_key...)
elem = unmarshal(mapper, T, Dict(zip(params_key, elem_values)); partial=true)
ret = f(elem_key, elem, params, params_key)
if (typeof(ret) <: Bool && ret == true) || (!(typeof(ret) <: Bool) && ret !== nothing)
release_connection(mapper.pool, conn)
return ret
end
end
end
release_connection(mapper.pool, conn)
end

function exists(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<:Model}; kwargs...)
(id, params) = extract_id_from_kwargs(mapper, T; kwargs...)
# Query with id
if id !== nothing
if id !== nothing
# Only id
if length(params) == 0
conn = get_connection(mapper.pool)
conn = get_connection(mapper.pool)
result = Redis.exists(conn, id)
release_connection(mapper.pool, conn)
release_connection(mapper.pool, conn)
return result
else
else
# ID & fields
conn = get_connection(mapper.pool)
params_key = collect(keys(params))
elem_values = Redis.hmget(conn, id, params_key...)
release_connection(mapper.pool, conn)
elem = unmarshal(mapper, T, Dict(zip(params_key, elem_values)); partial=true)
return all([params[k] == elem[k] for k in params_key])
elem = select_by_key_and_params(mapper, dbtype, T, id, params)
return all([params[k] == elem[k] for k in keys(params)])
end
else
conn = get_connection(mapper.pool)
cursor = -1
params_key = collect(keys(params))
while cursor != 0
(cursor, results) = Redis.scan(conn, cursor == -1 ? 0 : cursor, "match", redis_wildcard(T))
for elem_key in results
elem_values = Redis.hmget(conn, elem_key, params_key...)
elem = unmarshal(mapper, T, Dict(zip(params_key, elem_values)); partial=true)
found = all([params[k] == elem[k] for k in params_key])
if found
release_connection(mapper.pool, conn)
return found
end
end
else
found = (elem_id, elem, params, params_key)->all([params[k] == elem[k] for k in params_key])
ret = iterate_all(mapper, dbtype, T, params, found)
if ret !== nothing
return ret
end
release_connection(mapper.pool, conn)
end
return false
end

function Base.delete!(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<:Model}; kwargs...)
(id, params) = extract_id_from_kwargs(mapper, T; kwargs...)
if id !== nothing
if length(params) == 0
conn = get_connection(mapper.pool)
result = Redis.del(conn, id)
release_connection(mapper.pool, conn)
else
elem = select_by_key_and_params(mapper, dbtype, T, id, params)
if all([params[k] == elem[k] for k in keys(params)])
Redis.del(conn, id)
end
end
else
all_keys_to_delete = []
add_keys = (elem_key, elem, params, params_key)->begin
if all([params[k] == elem[k] for k in params_key])
push!(all_keys_to_delete, elem_key)
end
return nothing
end
ret = iterate_all(mapper, dbtype, T, params, add_keys)
conn = get_connection(mapper.pool)
for elem_key in all_keys_to_delete
Redis.del(conn, elem_key)
end
release_connection(mapper.pool, conn)
end
end

function select_all(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<:Model}; kwargs...)
params = Dict(kwargs...)
all_elems = []
found = (elem_key, elem, params, params_key)->begin
if all([params[k] == elem[k] for k in params_key])
push!(all_elems, elem)
end
return nothing
end
ret = iterate_all(mapper, dbtype, T, params, found)
return all_elems
end

2 comments on commit 6568129

@lucianolorenti
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/10554

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if Julia TagBot is installed, or can be done manually through the github interface, or via:

git tag -a v0.3.0 -m "<description of version>" 6568129e00383d890c510300d100fe5546ed6f79
git push origin v0.3.0

Please sign in to comment.