Select Git revision
Transaction.jl
-
Henrik tom Wörden authoredHenrik tom Wörden authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Transaction.jl 14.82 KiB
# ** header v3.0
# This file is a part of the CaosDB Project.
#
# Copyright (C) 2021 Indiscale GmbH <info@indiscale.com>
# Copyright (C) 2021 Florian Spreckelsen <f.spreckelsen@indiscale.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
# ** end header
#
module Transaction
export create_transaction,
add_retrieve_by_id,
add_query,
add_insert_entity,
add_update_entity,
add_delete_by_id,
add_retrieve_and_download_file_by_id,
execute,
get_result_set,
get_count_result,
get_result_at,
get_results,
execute_query,
retrieve
using CaosDB
"""
Struct containing a pointer to the wrapped cpp transaction
object. Meant for internal use; call
`CaosDB.Transaction.create_transaction` to create a transaction
object.
"""
mutable struct _Transaction
wrapped_transaction::Ptr{Cvoid}
_deletable::Bool
function _Transaction(managed_by_julia::Bool = false)
trans = new()
trans._deletable = false
if managed_by_julia
function f(t)
ccall(
(:caosdb_transaction_delete_transaction, CaosDB.library_name),
Cint,
(Ref{_Transaction},),
Ref{_Transaction}(t),
)
end
finalizer(f, trans)
end
return trans
end
end
"""
Struct containing a pointer to the wrapped cpp result set of a
transaction. The struct is meant for internal use only and shouldn't
be created directly by the user but is returned by, e.g.,
`get_result_set`.
"""
mutable struct _ResultSet
wrapped_result_set::Ptr{Cvoid}
_deletable::Bool
function _ResultSet()
rs = new()
rs._deletable = false
return rs
end
end
"""
create_transaction(name::AbstractString = "default")
Return a transaction created with the connection of the given name. If
none is given, the defult connection is used.
"""
function create_transaction(name::AbstractString = "default")
connection = CaosDB.Connection.get_connection(name)
return create_transaction(connection)
end
"""
function create_transaction(connection::Ref{CaosDB.Connection._Connection})
Return a transactioncreated with the given connection object.
"""
function create_transaction(connection::Ref{CaosDB.Connection._Connection})
transaction = Ref{_Transaction}(_Transaction(true))
err_code = ccall(
(:caosdb_connection_connection_create_transaction, CaosDB.library_name),
Cint,
(Ref{CaosDB.Connection._Connection}, Ref{_Transaction}),
connection,
transaction,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
return transaction
end
"""
function add_retrieve_by_id(transaction::Ref{_Transaction}, id::AbstractString)
Add a sub-request to retrieve a single entity by its `id` to the given
`transaction`.
!!! info
This does not execute the transaction.
"""
function add_retrieve_by_id(transaction::Ref{_Transaction}, id::AbstractString)
err_code = ccall(
(:caosdb_transaction_transaction_retrieve_by_id, CaosDB.library_name),
Cint,
(Ref{_Transaction}, Cstring),
transaction,
id,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
end
"""
function add_insert_entity(transaction::Ref{_Transaction}, entity::Ref{_CaosDB.Entity.Entity})
Add a sub-request to insert a single entity to the given `transaction`.
!!! info
This does not execute the transaction.
"""
function add_insert_entity(
transaction::Ref{_Transaction},
entity::Ref{CaosDB.Entity._Entity},
)
err_code = ccall(
(:caosdb_transaction_transaction_insert_entity, CaosDB.library_name),
Cint,
(Ref{_Transaction}, Ref{CaosDB.Entity._Entity}),
transaction,
entity,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
end
"""
function add_update_entity(transaction::Ref{_Transaction}, entity::Ref{_CaosDB.Entity.Entity})
Add a sub-request to update a single entity to the given `transaction`.
!!! info
This does not execute the transaction.
"""
function add_update_entity(
transaction::Ref{_Transaction},
entity::Ref{CaosDB.Entity._Entity},
)
err_code = ccall(
(:caosdb_transaction_transaction_update_entity, CaosDB.library_name),
Cint,
(Ref{_Transaction}, Ref{CaosDB.Entity._Entity}),
transaction,
entity,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
end
"""
function add_delete_by_id(transaction::Ref{_Transaction}, id::AbstractString)
Add a sub-request to delete a single entity to the given `transaction`.
!!! info
This does not execute the transaction.
"""
function add_delete_by_id(transaction::Ref{_Transaction}, id::AbstractString)
err_code = ccall(
(:caosdb_transaction_transaction_delete_by_id, CaosDB.library_name),
Cint,
(Ref{_Transaction}, Cstring),
transaction,
id,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
end
"""
function add_retrieve_by_id(
transaction::Ref{_Transaction},
ids::Vector{T},
) where {T<:AbstractString}
Add a sub-request to retrieve several entities by their `ids` to the
given `transaction`.
!!! info
This does not execute the transaction.
"""
function add_retrieve_by_id(
transaction::Ref{_Transaction},
ids::Vector{T},
) where {T<:AbstractString}
len = Cint(length(ids))
err_code = ccall(
(:caosdb_transaction_transaction_retrieve_by_ids, CaosDB.library_name),
Cint,
(Ref{_Transaction}, Ptr{Ptr{Cchar}}, Cint),
transaction,
ids,
len,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
end
"""
function add_retrieve_and_download_file_by_id(
transaction::Ref{_Transaction},
id::AbstractString,
path::AbstractString,
)
Add a sub-request to retrieve and download a single entity (File) to the given `transaction`.
!!! info
This does not execute the transaction.
"""
function add_retrieve_and_download_file_by_id(
transaction::Ref{_Transaction},
id::AbstractString,
path::AbstractString,
)
err_code = ccall(
(
:caosdb_transaction_transaction_retrieve_and_download_file_by_id,
CaosDB.library_name,
),
Cint,
(Ref{_Transaction}, Cstring, Cstring),
transaction,
id,
path,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
end
"""
function add_query(transaction::Ref{_Transaction}, query::AbstractString)
Add a query sub-request to the given `transaction`.
!!! warning
Only COUNT queris and FIND queries (and no SELECT queries) are
currently supported.
!!! info
This does not execute the transaction
"""
function add_query(transaction::Ref{_Transaction}, query::AbstractString)
err_code = ccall(
(:caosdb_transaction_transaction_query, CaosDB.library_name),
Cint,
(Ref{_Transaction}, Cstring),
transaction,
query,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
end
"""
function execute(transaction::Ref{_Transaction})
Send the given `transaction` to the CaosDB server for excecution and
wait for it to finish.
"""
function execute(transaction::Ref{_Transaction})
err_code = ccall(
(:caosdb_transaction_transaction_execute, CaosDB.library_name),
Cint,
(Ref{_Transaction},),
transaction,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
end
"""
function get_result_set(transaction::Ref{_Transaction})
Return the result set of the given `transaction`.
"""
function get_result_set(transaction::Ref{_Transaction})
results = Ref{_ResultSet}(_ResultSet())
err_code = ccall(
(:caosdb_transaction_transaction_get_result_set, CaosDB.library_name),
Cint,
(Ref{_Transaction}, Ref{_ResultSet}),
transaction,
results,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
return results
end
"""
function get_count_result(transaction::Ref{_Transaction})
Return the number of results of the COUNT query in the given `transaction`.
!!! info
This is only a meaningful quantity if there actually was a COUNT
query in the `transaction`, and it already has been executed. In
all other cases the return value will be -1.
"""
function get_count_result(transaction::Ref{_Transaction})
out = Ref{Clong}(0)
err_code = ccall(
(:caosdb_transaction_transaction_get_count_result, CaosDB.library_name),
Cint,
(Ref{_Transaction}, Ref{Clong}),
transaction,
out,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
return out[]
end
"""
function get_result_size(results::Ref{_ResultSet})
Return the size of the given `results`, i.e., the number of entities
or other responses returned in this result set.
"""
function get_result_size(results::Ref{_ResultSet})
size = Ref{Cint}(0)
err_code = ccall(
(:caosdb_transaction_result_set_size, CaosDB.library_name),
Cint,
(Ref{_ResultSet}, Ref{Cint}),
results,
size,
)
CaosDB.Exceptions.evaluate_return_code(err_code)
return size[]
end
"""
function get_result_at(results::Ref{_ResultSet}, index::Cint)
Return the entity at position `index` of the given `results`.
"""
function get_result_at(results::Ref{_ResultSet}, index::Cint)
size = get_result_size(results)
if index > size
throw(
DomainError(
index,
"You tried to access the result at position $index but the result set only has $size results.",
),
)
end
entity = Ref{CaosDB.Entity._Entity}(CaosDB.Entity._Entity())
err_code = ccall(
(:caosdb_transaction_result_set_at, CaosDB.library_name),
Cint,
(Ref{_ResultSet}, Ref{CaosDB.Entity._Entity}, Cint),
results,
entity,
index - Cint(1),
)
CaosDB.Exceptions.evaluate_return_code(err_code)
return entity
end
"""
function get_result_at(results::Ref{_ResultSet}, index::Integer)
Convenience wrapper for `get_result_at(::Ref{_ResultSet},
::Cint)`. Convert the given `index` to Int32 and return the result at
position `index` of `results`.
"""
function get_result_at(results::Ref{_ResultSet}, index::Integer)
return get_result_at(results, Cint(index))
end
"""
function get_results(result_set::Ref{_ResultSet})
Return al results of the given `result_set`.
"""
function get_results(result_set::Ref{_ResultSet})
size = get_result_size(result_set)
return [get_result_at(result_set, Cint(ii)) for ii = 1:size]
end
"""
function get_results(transaction::Ref{_Transaction})
Return all results of the given `transaction`.
"""
function get_results(transaction::Ref{_Transaction})
result_set = get_result_set(transaction)
return get_results(result_set)
end
"""
function execute_query(
query::AbstractString,
name::AbstractString = "default"
)
Execute the given `query` and return its results. Use the connection
with the given `name`. If none is given, the default connection is
used.
!!! info
Since only the resulting entities are returned, this only makes
sense for FIND (and, in the future, SELECT) queries. To get the
result of a `COUNT` query, you have to execute the transaction
yourself using `create_transaction`, `add_query`, and `execute`,
and get the result with `get_count_result`.
"""
function execute_query(query::AbstractString, name::AbstractString = "default")
transaction = create_transaction(name)
add_query(transaction, query)
execute(transaction)
return get_results(transaction)
end
"""
function execute_query(
query::AbstractString,
connection::Ref{CaosDB.Connection._Connection}
)
Execute the given `query` and return its results. Use the given
`connection`.
!!! info
Since only the resulting entities are returned, this only makes
sense for FIND (and, in the future, SELECT) queries. To get the
result of a `COUNT` query, you have to execute the transaction
yourself using `create_transaction`, `add_query`, and `execute`,
and get the result with `get_count_result`.
"""
function execute_query(
query::AbstractString,
connection::Ref{CaosDB.Connection._Connection},
)
transaction = create_transaction(connection)
add_query(transaction, query)
execute(transaction)
return get_results(transaction)
end
"""
function retrieve(id::AbstractString, name::AbstractString = "default")
Retrieve and return the entity with the given `id`. Use the connection
with the given `name`. If none is provided, the default connection is
used.
"""
function retrieve(id::AbstractString, name::AbstractString = "default")
transaction = create_transaction(name)
add_retrieve_by_id(transaction, id)
execute(transaction)
return get_results(transaction)[1]
end
"""
function retrieve(id::AbstractString, connection::Ref{CaosDB.Connection._Connection})
Retrieve and return the entity with the given `id`. Use the given
`connection`.
"""
function retrieve(id::AbstractString, connection::Ref{CaosDB.Connection._Connection})
transaction = create_transaction(connection)
add_retrieve_by_id(transaction, id)
execute(transaction)
return get_results(transaction)[1]
end
"""
function retrieve(
ids::Vector{T},
name::AbstractString = "default",
) where {T<:AbstractString}
Retrieve and return the entities with the given `ids`. Use the
connection of the given `name`. If none is provided, the default
connection is used.
"""
function retrieve(
ids::Vector{T},
name::AbstractString = "default",
) where {T<:AbstractString}
transaction = create_transaction(name)
add_retrieve_by_id(transaction, ids)
execute(transaction)
return get_results(transaction)
end
"""
function retrieve(
ids::Vector{T},
connection::Ref{CaosDB.Connection._Connection},
) where {T<:AbstractString}
Retrieve and return the entities with the given `ids`. Use the given
`connection`.
"""
function retrieve(
ids::Vector{T},
connection::Ref{CaosDB.Connection._Connection},
) where {T<:AbstractString}
transaction = create_transaction(connection)
add_retrieve_by_id(transaction, ids)
execute(transaction)
return get_results(transaction)
end
end # Transaction