summaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src/db')
-rw-r--r-- | src/db/include/db_query.hrl | 27 | ||||
-rw-r--r-- | src/db/src/storage_access.erl | 20 | ||||
-rw-r--r-- | src/db/src/storage_query.erl | 90 | ||||
-rw-r--r-- | src/db/src/storage_update.erl | 36 |
4 files changed, 127 insertions, 46 deletions
diff --git a/src/db/include/db_query.hrl b/src/db/include/db_query.hrl index bdd9dc1..45c040b 100644 --- a/src/db/include/db_query.hrl +++ b/src/db/include/db_query.hrl @@ -1,6 +1,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-type db_user() :: ({'user', any()} | 'admin' | 'any'). + -record ( set_field, @@ -26,9 +28,30 @@ { field :: non_neg_integer(), ix :: non_neg_integer(), - update :: list(db_query()) + ops :: list(db_query_op()) + } +). + +-record +( + set_user, + { + user :: db_user() + } +). + +-record +( + db_query, + { + db :: atom(), + id :: any(), + user :: db_user(), + ops :: list(db_query_master_op()) } ). --type db_query() :: (#set_field{} | #add_to_field{} | #update_indexed{}). +-type db_query_op() :: (#set_field{} | #add_to_field{} | #update_indexed{}). +-type db_query_master_op() :: (db_query_op() | #set_user{}). +-type db_query() :: #db_query{}. diff --git a/src/db/src/storage_access.erl b/src/db/src/storage_access.erl index be481ee..c58f26d 100644 --- a/src/db/src/storage_access.erl +++ b/src/db/src/storage_access.erl @@ -19,8 +19,10 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -get_value([]) -> []; -get_value([#regval{ val = Val }]) -> [Val]. +get_value ([]) -> not_found; +get_value ([Regval]) -> {ok, Regval}. + +get_value(DB, ID) -> get_value(mnesia:read(DB, ID)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -32,11 +34,13 @@ insert (DB, ID, Owner, Value) -> StoredItem = #regval{ id = ID, owner = Owner, val = Value }, % FIXME: handle return value, mnesia:write -> (transaction abort | ok). % FIXME: is this an atomic OP? Is the lock freed afterwards? - mnesia:write(DB, StoredItem, sticky_write). + mnesia:write(DB, StoredItem, sticky_write), + ok. -update (DB, ID, Update) -> +update (DB, ID, Query) -> + {ok, Item} = get_value(DB, ID), + {ok, UpdatedItem} = db_query:apply_to(Query, Item), % FIXME: handle return value, mnesia:write -> (transaction abort | ok). - case mnesia:read(DB, ID) of - [] -> error; - _ -> unimplemented - end. + % FIXME: is this an atomic OP? Is the lock freed afterwards? + mnesia:write(DB, UpdatedItem, sticky_write), + ok. diff --git a/src/db/src/storage_query.erl b/src/db/src/storage_query.erl new file mode 100644 index 0000000..5b37f2d --- /dev/null +++ b/src/db/src/storage_query.erl @@ -0,0 +1,90 @@ +-module(storage_query). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-include("../include/db_query.hrl"). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export([apply_to/2]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec get_user (db_query()) -> db_user(). +get_user (#db_query{ user = Result }) -> Result. + +-spec apply_update_indexed (#update_indexed{}, any()) -> any(). +apply_update_indexed (Op, Elem) -> + FieldNumber = Op#update_indexed.field, + IX = Op#update_indexed.ix, + Ops = Op#update_indexed.ops, + + IndexedFieldValue = element(FieldNumber, Elem), + ArrayValue = array:get(IX, IndexedFieldValue), + UpdatedArrayValue = lists:foldl(fun apply_op_to/2, ArrayValue, Ops), + UpdatedIndexedFieldValue = array:set(IX, UpdatedArrayValue), + + setelement(FieldNumber, Elem, UpdatedIndexedFieldValue). + +-spec apply_add_to_field (#add_to_field{}, any()) -> any(). +apply_add_to_field (Op, Elem) -> + FieldNumber = Op#add_to_field.field, + NewValues = Op#add_to_field.values, + AddToHead = Op#add_to_field.head, + + CurrentValues = element(FieldNumber, Elem), + UpdatedValues = + case AddToHead of + true -> (NewValues ++ CurrentValues); + _ -> (CurrentValues ++ NewValues) + end, + + setelement(FieldNumber, Elem, UpdatedValues). + +-spec apply_set_field (#set_field{}, any()) -> any(). +apply_set_field (Op, Elem) -> + FieldNumber = Op#set_field.field, + NewValue = Op#set_field.value, + + setelement(FieldNumber, Elem, NewValue). + +-spec apply_op_to (db_query_op(), any()) -> any(). +apply_op_to (Op, Elem) when is_record(Elem, set_field) -> + apply_set_field(Op, Elem); +apply_op_to (Op, Elem) when is_record(Elem, add_to_field) -> + apply_add_to_field(Op, Elem); +apply_op_to (Op, Elem) when is_record(Elem, update_indexed) -> + apply_update_indexed(Op, Elem). + +-spec apply_master_op_to + ( + db_query_master_op(), + db_item:type() + ) + -> db_item:type(). +apply_master_op_to (MOp, Elem) when is_record(MOp, set_user) -> + NewUser = MOp#set_user.user, + + db_item:set_user(NewUser, Elem); +apply_master_op_to (MOp, Elem) -> + OldValue = db_item:get_value(Elem), + NewValue = apply_op_to(MOp, OldValue), + + db_item:set_value(NewValue, Elem). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec apply_to + ( + db_query(), + db_item:type() + ) + -> ({'ok', db_item:type()} | 'error'). +apply_to (DBQuery, DBItem) -> + true = db_user:has_permission(db_item:get_user(DBItem), get_user(DBQuery)), + {ok, apply_master_op_to(DBQuery, DBItem)}. + diff --git a/src/db/src/storage_update.erl b/src/db/src/storage_update.erl deleted file mode 100644 index c3a53e4..0000000 --- a/src/db/src/storage_update.erl +++ /dev/null @@ -1,36 +0,0 @@ --module(storage_update). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --include("../include/db_query.hrl"). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export([apply_to/2]). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -apply_to (#set_field{ field = Field, value = Value }, Elem) -> - setelement(Field, Elem, Value); -apply_to (#add_to_field{ field = Field, values = Values, head = Head }, Elem) -> - CurrentValues = element(Field, Elem), - UpdatedValues = - case Head of - true -> (Values ++ CurrentValues); - _ -> (CurrentValues ++ Values) - end, - setelement(Field, Elem, UpdatedValues); -apply_to (#update_indexed{ field = Field, ix = IX, update = Update}, Elem) -> - IndexedFieldValue = element(Field, Elem), - ArrayValue = array:get(IX, IndexedFieldValue), - UpdatedArrayValue = lists:foldl(fun apply_to/2, ArrayValue, Update), - UpdatedIndexedFieldValue = array:set(IX, UpdatedArrayValue), - setelement(Field, Elem, UpdatedIndexedFieldValue). |