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

Commit

Permalink
Add the option to select fields returned by select_all
Browse files Browse the repository at this point in the history
  • Loading branch information
lucianolorenti committed Mar 15, 2020
1 parent 24329fe commit 5b88e93
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Project.toml
@@ -1,7 +1,7 @@
name = "StructDatabaseMapping"
uuid = "66daddfc-c305-4fd9-8f84-fb59daccc546"
authors = ["Luciano Rolando Lorenti <lucianolorenti@gmail.com>"]
version = "0.3.1"
version = "0.3.2"

[deps]
DBInterface = "a10d1c49-ce27-4219-8d33-6db1a4562965"
Expand Down
35 changes: 22 additions & 13 deletions src/NonRelational/Redis.jl
Expand Up @@ -79,16 +79,21 @@ function select_by_key_and_params(mapper::DBMapper, dbtype::Type{Redis.RedisConn
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)
function iterate_all(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<:Model},
conditions, apply_function, fields::Array{Symbol}=Symbol[])
conn = get_connection(mapper.pool)
cursor = -1
params_key = collect(keys(params))
conditions_fields = collect(keys(conditions))
if isempty(fields)
fields = column_names(mapper, T)
end
fields_to_obtain = union(conditions_fields, fields)
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)
for elem_key in results
elem_values = Redis.hmget(conn, elem_key, fields_to_obtain...)
elem = unmarshal(mapper, T, Dict{Symbol, Any}(zip(fields_to_obtain, elem_values)); partial=true)
ret = apply_function(elem_key, elem, conditions, conditions_fields)
if (typeof(ret) <: Bool && ret == true) || (!(typeof(ret) <: Bool) && ret !== nothing)
release_connection(mapper.pool, conn)
return ret
Expand Down Expand Up @@ -122,8 +127,8 @@ function exists(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<
end
return false
end

function Base.delete!(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<:Model}; kwargs...)
import Base:delete!
function 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
Expand Down Expand Up @@ -153,15 +158,19 @@ function Base.delete!(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::
end
end

function select_all(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<:Model}; kwargs...)
params = Dict(kwargs...)
function select_all(mapper::DBMapper, dbtype::Type{Redis.RedisConnection}, T::Type{<:Model}; fields::Array{Symbol}=[], kwargs...) ::Array{T}
conditions = Dict(kwargs...)
all_elems = []
found = (elem_key, elem, params, params_key)->begin
found_function = (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
ret = iterate_all(mapper, dbtype, T, conditions, found_function, fields)
if isempty(all_elems)
return nothing
else
return [T(;unmarshal(mapper, T, elem, partial=!isempty(fields))...) for elem in all_elems]
end
end
24 changes: 16 additions & 8 deletions src/Relational/Relational.jl
Expand Up @@ -166,7 +166,9 @@ function totuple(mapper::DBMapper, table::Table, dbtype::DataType, db_results) :
db_data = Dict(field=>getindex(row, field)
for field in propertynames(row))
for field in fieldlist(table)
push!(r, field.struct_field=>unmarshal(mapper, dbtype, field.type, db_data[field.name]))
if haskey(db_data, field.name)
push!(r, field.struct_field=>unmarshal(mapper, dbtype, field.type, db_data[field.name]))
end
end
push!(results, r)
end
Expand All @@ -177,26 +179,32 @@ function totuple(results)
[(;(prop=>getindex(row, prop) for prop in propertynames(row))...) for row in results]
end

function select_query(mapper::DBMapper, T::Type{<:Model}; select_one=true, kwargs...)
function select_query(mapper::DBMapper, T::Type{<:Model}; select_one=true, fields::Array{Symbol}=Symbol[], kwargs...)
dbtype = mapper.pool.dbtype
table = mapper.tables[T]
cnames = join(column_names(mapper, T), ", ")
if isempty(fields)
fields = column_names(mapper, T)
end
cnames = join(fields, ", ")
conditions = join(["$field=?" for (field, value) in kwargs], " AND ")
sql = """
SELECT $cnames
FROM $(table.name)
WHERE $(conditions)
"""
if !isempty(conditions)
sql *= """
WHERE $(conditions)"""
end
if select_one
sql *= " LIMIT 1"
end
return clean_sql(sql)
end

function select(mapper::DBMapper, T::Type{<:Model}; select_one=true, kwargs...)
function select(mapper::DBMapper, T::Type{<:Model}; select_one=true, fields::Array{Symbol}=Symbol[], kwargs...)
dbtype = mapper.pool.dbtype
table = mapper.tables[T]
sql = select_query(mapper, T; select_one=select_one, kwargs...)
sql = select_query(mapper, T; select_one=select_one, fields=fields, kwargs...)
values = [v[2] for v in kwargs]
@info sql
conn = get_connection(mapper.pool)
Expand All @@ -215,8 +223,8 @@ function select_one(mapper::DBMapper, ::Type{Relational}, T::Type{<:Model}; kwar
end
end

function select_all(mapper::DBMapper, ::Type{Relational}, T::Type{<:Model}; kwargs...) :: Array{T}
result = select(mapper, T; select_one=false, kwargs...)
function select_all(mapper::DBMapper, ::Type{Relational}, T::Type{<:Model}; fields::Array{Symbol} =Symbol[], kwargs...) :: Array{T}
result = select(mapper, T; select_one=false, fields=fields, kwargs...)
if isempty(result)
return T[]
else
Expand Down
10 changes: 5 additions & 5 deletions src/StructDatabaseMapping.jl
Expand Up @@ -569,7 +569,7 @@ function Base.delete!(mapper::DBMapper, elem::T) where T<:Model
end

"""
select_all(mapper::DBMapper, T::Type{<:Model}; kwargs...)
select_all(mapper::DBMapper, T::Type{<:Model}; ; fields::Array{Symbol}=[], kwargs...)
Select all the elements that meet a criteria
Expand All @@ -583,12 +583,12 @@ struct Author <: Model ... end
select_all(mapper, Author, age=30)
```
"""
function select_all(mapper::DBMapper, T::Type{<:Model}; kwargs...)
function select_all(mapper::DBMapper, T::Type{<:Model}; fields::Array{Symbol}=Symbol[], kwargs...)
check_valid_type(mapper, T)
return select_all(mapper, mapper.pool.dbtype, T; kwargs...)
return select_all(mapper, mapper.pool.dbtype, T; fields=fields, kwargs...)
end
function select_all(mapper::DBMapper, dbtype::DataType, T::Type{<:Model}; kwargs...)
return select_all(mapper, database_kind(dbtype), T; kwargs...)
function select_all(mapper::DBMapper, dbtype::DataType, T::Type{<:Model}; fields::Array{Symbol}=Symbol[], kwargs...)
return select_all(mapper, database_kind(dbtype), T; fields=fields, kwargs...)
end

"""
Expand Down
23 changes: 18 additions & 5 deletions test/includes/basic_test.jl
Expand Up @@ -2,13 +2,15 @@ mutable struct Author <: Model
id::DBId{Integer}
name::String
age::Integer
country::String
date::DateTime
end
function Author(;id::Union{Integer, Nothing} = nothing,
name::String="",
age::Integer=0,
country::String="",
date::DateTime=now())
return Author(id, name, age, date)
return Author(id, name, age, country, date)
end
mutable struct Book <: Model
id::DBId{String}
Expand Down Expand Up @@ -62,18 +64,21 @@ function _test_basic_functionalities(creator)
create_table(mapper, Author)
create_table(mapper, Book)

author = Author(name="pirulo", age=50)
author = Author(name="pirulo", age=50, country="Argentina")
insert!(mapper, author)
@test !isnothing(author.id.x)
id = author.id.x

author = Author(name="Author 1", age=3)
author = Author(name="Author 1", age=3, country="Argentina")
insert!(mapper, author)

author = Author(name="Author 2", age=3)
author = Author(name="Author 2", age=3, country="Brasil")
insert!(mapper, author)

author = Author(name="Author 3", age=3)
author = Author(name="Author 5", age=25, country="Italia")
insert!(mapper, author)

author = Author(name="Author 3", age=3, country="Uruguay")
insert!(mapper, author)

@test StructDatabaseMapping.exists(mapper, Author, name="Enrique Banch") == false
Expand All @@ -87,8 +92,16 @@ function _test_basic_functionalities(creator)


authors = select_all(mapper, Author, age=3)
@test isa(authors[1], Author)
@test length(authors) == 3

authors = select_all(mapper, Author)
@test length(authors) == 5

authors = select_all(mapper, Author, age=3, fields=[:name, :country])
@test Set([author.country for author in authors]) == Set(["Brasil", "Argentina", "Uruguay"])


a = select_one(mapper, Author, id=999)
@test isnothing(a)
a = select_one(mapper, Author, id=id)
Expand Down
1 change: 1 addition & 0 deletions test/postgresql/TestLibPQ.jl
Expand Up @@ -34,6 +34,7 @@ function test_create_tables()
@test (StructDatabaseMapping.create_table_query(mapper, Author)
== "CREATE TABLE IF NOT EXISTS author (" *
"age INTEGER NOT NULL, " *
"country VARCHAR NOT NULL, " *
"date TIMESTAMP NOT NULL, " *
"id SERIAL PRIMARY KEY, " *
"name VARCHAR NOT NULL)")
Expand Down
1 change: 1 addition & 0 deletions test/sqlite/TestSQLite.jl
Expand Up @@ -27,6 +27,7 @@ function test_create_tables()
@test (StructDatabaseMapping.create_table_query(mapper, Author)
== "CREATE TABLE IF NOT EXISTS author (" *
"age INTEGER NOT NULL, " *
"country VARCHAR NOT NULL, " *
"date DATETIME NOT NULL, " *
"id INTEGER PRIMARY KEY, " *
"name VARCHAR NOT NULL)")
Expand Down

2 comments on commit 5b88e93

@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/11019

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.2 -m "<description of version>" 5b88e9382f07ab3c6c5054a78f9c199bc1baa0a7
git push origin v0.3.2

Please sign in to comment.