-module(ts_entry). -export([create_table/1, new/1, update/1, lookup/3, list_asc/3, list_desc/3]). -include("ts_db_records.hrl"). -include_lib("stdlib/include/qlc.hrl"). create_table(TableOpts) -> mnesia:create_table(ts_entry, TableOpts ++ [{attributes, record_info(fields, ts_entry)}, {type, ordered_set}, {index, [timestamp]}]). new(ER = #ts_entry{}) -> {atmoic, NewRow} = mnesia:transaction(fun() -> {Username, TimelineId, _} = ER#ts_entry.ref, NextId = id_counter:next_counter(ts_entry_id), NewRow = ER#ts_entry{ref = {Username, TimelineId, NextId}}, ok = mnesia:write(NewRow), NewRow end), {ok, NewRow}. update(ER = #ts_entry{}) -> % look for existing record case mnesia:dirty_read(ts_entry, ER#ts_entry.ref) of % record does not exist [] -> no_record; % record exists, update it [_Record] -> mnesia:dirty_write(ER) end. lookup(Username, TimelineId, EntryId) -> case mnesia:dirty_read(ts_entry, {Username, TimelineId, EntryId}) of [] -> no_record; [Entry] -> Entry end. list({Username, Timeline}, Start, Length, OrderFun) when is_integer(Start) and is_integer(Length) -> {atomic, Entries} = mnesia:transaction(fun() -> % match the username and timeline MatchHead = #ts_entry{ref = {Username, Timeline, '_'}, _='_'}, % select all records that match mnesia:select(ts_entry, [{MatchHead, [], ['$_']}]) end), % sort SortedEntries = lists:sort(OrderFun, Entries), % return only the range selected. % TODO: can we do this without selecting all entries? lists:sublist(SortedEntries, Start + 1, Length); list({Username, Timeline}, StartDateTime, EndDateTime, OrderFun) -> % compute the seconds from datetimes StartSeconds = calendar:datetime_to_gregorian_seconds(StartDateTime), EndSeconds = calendar:datetime_to_gregorian_seconds(EndDateTime), % select all entries from the timeline that are within the time range {atomic, Entries} = mnesia:transaction(fun() -> % match the username and timeline id MatchHead = #ts_entry{ref = {Username, Timeline, '_'}, timestamp='$1', _='_'}, % guards for the time range StartGuard = {'>=', '$1', StartSeconds}, EndGuard = {'<', '$1', EndSeconds}, mnesia:select(ts_entry, [{MatchHead, [StartGuard, EndGuard], ['$_']}]) end), % sort lists:sort(OrderFun, Entries). list_asc(TimelineRef, Start, Length) when is_integer(Start) and is_integer(Length) -> list(TimelineRef, Start, Length, fun timestamp_asc/2); list_asc(TimelineRef, StartDateTime, EndDateTime) -> list(TimelineRef, StartDateTime, EndDateTime, fun timestamp_asc/2). list_desc(TimelineRef, Start, Length) when is_integer(Start) and is_integer(Length) -> list(TimelineRef, Start, Length, fun timestamp_desc/2); list_desc(TimelineRef, StartDateTime, EndDateTime) -> list(TimelineRef, StartDateTime, EndDateTime, fun timestamp_desc/2). timestamp_asc(E1, E2) -> E1#ts_entry.timestamp > E2#ts_entry.timestamp. timestamp_desc(E1, E2) -> E1#ts_entry.timestamp < E2#ts_entry.timestamp.