Permalink
Browse files

Merge branch 'master' of github.com:evanmiller/boss_db

  • Loading branch information...
2 parents 753fcdb + 9943a4d commit b297b5005f38eb20186ec05d98f3e7f450a41482 Evan Miller committed Jul 26, 2012
View
63 src/boss_db.erl
@@ -8,9 +8,6 @@
find/1,
find/2,
find/3,
- find/4,
- find/5,
- find/6,
find_first/2,
find_first/3,
find_last/2,
@@ -79,62 +76,44 @@ find(_) ->
%% @doc Query for BossRecords. Returns all BossRecords of type
%% `Type' matching all of the given `Conditions'
find(Type, Conditions) ->
- find(Type, Conditions, all).
-
-%% @spec find(Type::atom(), Conditions, Max::integer() | all ) -> [ BossRecord ]
-%% @doc Query for BossRecords. Returns up to `Max' number of BossRecords of type
-%% `Type' matching all of the given `Conditions'
-find(Type, Conditions, Max) ->
- find(Type, Conditions, Max, 0).
-
-%% @spec find( Type::atom(), Conditions, Max::integer() | all, Skip::integer() ) -> [ BossRecord ]
-%% @doc Query for BossRecords. Returns up to `Max' number of BossRecords of type
-%% `Type' matching all of the given `Conditions', skipping the first `Skip' results.
-find(Type, Conditions, Max, Skip) ->
- find(Type, Conditions, Max, Skip, id).
-
-%% @spec find( Type::atom(), Conditions, Max::integer() | all, Skip::integer(), Sort::atom() ) -> [ BossRecord ]
-%% @doc Query for BossRecords. Returns up to `Max' number of BossRecords of type
-%% `Type' matching all of the given `Conditions', skipping the
-%% first `Skip' results, sorted on the attribute `Sort'.
-find(Type, Conditions, Max, Skip, Sort) ->
- find(Type, Conditions, Max, Skip, Sort, str_ascending).
-
-%% @spec find( Type::atom(), Conditions, Max::integer() | all, Skip::integer(), Sort::atom(), SortOrder ) -> [ BossRecord ]
-%% SortOrder = num_ascending | num_descending | str_ascending | str_descending
-%% @doc Query for BossRecords. Returns up to `Max' number of BossRecords of type
-%% Type matching all of the given `Conditions', skipping the
-%% first `Skip' results, sorted on the attribute `Sort'. `SortOrder' specifies whether
-%% to treat values as strings or as numbers, and whether to sort ascending or
-%% descending. (`SortOrder' = `num_ascending', `num_descending', `str_ascending', or
-%% `str_descending')
-%%
-%% Note that Time attributes are stored internally as numbers, so you should
-%% sort them numerically.
-
-find(Type, Conditions, Max, Skip, Sort, SortOrder) ->
+ find(Type, Conditions, []).
+
+%% @spec find(Type::atom(), Conditions, Options::proplist()) -> [ BossRecord ]
+%% @doc Query for BossRecords. Returns BossRecords of type
+%% `Type' matching all of the given `Conditions'. Options may include
+%% `limit' (maximum number of records to return), `offset' (number of records
+%% to skip), `order_by' (attribute to sort on), and `descending' (whether to
+%% sort the values from highest to lowest)
+find(Type, Conditions, Options) ->
+ Max = proplists:get_value(limit, Options, all),
+ Skip = proplists:get_value(offset, Options, 0),
+ Sort = proplists:get_value(order_by, Options, id),
+ SortOrder = case proplists:get_value(descending, Options) of
+ true -> descending;
+ _ -> ascending
+ end,
db_call({find, Type, normalize_conditions(Conditions), Max, Skip, Sort, SortOrder}).
%% @spec find_first( Type::atom(), Conditions ) -> Record | undefined
%% @doc Query for the first BossRecord of type `Type' matching all of the given `Conditions'
find_first(Type, Conditions) ->
- return_one(find(Type, Conditions, 1)).
+ return_one(find(Type, Conditions, [{limit, 1}])).
%% @spec find_first( Type::atom(), Conditions, Sort::atom() ) -> Record | undefined
%% @doc Query for the first BossRecord of type `Type' matching all of the given `Conditions',
%% sorted on the attribute `Sort'.
find_first(Type, Conditions, Sort) ->
- return_one(find(Type, Conditions, 1, 0, Sort)).
+ return_one(find(Type, Conditions, [{limit, 1}, {order_by, Sort}])).
%% @spec find_last( Type::atom(), Conditions ) -> Record | undefined
%% @doc Query for the last BossRecord of type `Type' matching all of the given `Conditions'
find_last(Type, Conditions) ->
- return_one(find(Type, Conditions, 1, 0, id, str_descending)).
+ return_one(find(Type, Conditions, [{limit, 1}, descending])).
-%% @spec find_last( Type::atom(), Conditions ) -> Record | undefined
+%% @spec find_last( Type::atom(), Conditions, Sort ) -> Record | undefined
%% @doc Query for the last BossRecord of type `Type' matching all of the given `Conditions'
find_last(Type, Conditions, Sort) ->
- return_one(find(Type, Conditions, 1, 0, Sort, str_descending)).
+ return_one(find(Type, Conditions, [{limit, 1}, {order_by, Sort}, descending])).
%% @spec count( Type::atom() ) -> integer()
%% @doc Count the number of BossRecords of type `Type' in the database.
View
10 src/boss_db_mock_controller.erl
@@ -24,7 +24,7 @@ handle_call({find, Type, Conditions, Max, Skip, SortBy, SortOrder}, _From, [{Dic
Records = do_find(Dict, Type, Conditions, Max, Skip, SortBy, SortOrder),
{reply, Records, State};
handle_call({count, Type, Conditions}, _From, [{Dict, _IdCounter}|_] = State) ->
- Records = do_find(Dict, Type, Conditions, all, 0, id, str_ascending),
+ Records = do_find(Dict, Type, Conditions, all, 0, id, ascending),
{reply, length(Records), State};
handle_call({delete, Id}, _From, [{Dict, IdCounter}|OldState]) ->
{reply, ok, [{dict:erase(Id, Dict), IdCounter}|OldState]};
@@ -87,13 +87,9 @@ do_find(Dict, Type, Conditions, Max, Skip, SortBy, SortOrder) ->
AttributeA = sortable_attribute(RecordA, SortBy),
AttributeB = sortable_attribute(RecordB, SortBy),
case SortOrder of
- str_ascending ->
+ ascending ->
AttributeA < AttributeB;
- str_descending ->
- AttributeA > AttributeB;
- num_ascending ->
- AttributeA < AttributeB;
- num_descending ->
+ descending ->
AttributeA > AttributeB
end
end,
View
20 src/boss_db_test_app.erl
@@ -133,28 +133,20 @@ run_tests() ->
end,
[
fun(_) ->
- Res = boss_db:find(boss_db_test_model, [], 1),
+ Res = boss_db:find(boss_db_test_model, [], [{limit, 1}]),
{length(Res) =:= 1, "Max not obeyed"}
end,
fun(_) ->
- Res = boss_db:find(boss_db_test_model, [], all, 1),
+ Res = boss_db:find(boss_db_test_model, [], [{offset, 1}]),
{length(Res) =:= 2, "Skip not obeyed"}
end,
fun([_Id1, _Id2, Id3]) ->
- Res = boss_db:find(boss_db_test_model, [], 1, 0, some_text, str_ascending),
- {(hd(Res)):id() =:= Id3, "Sort str_ascending failed"}
+ Res = boss_db:find(boss_db_test_model, [], [{limit, 1}, {order_by, some_text}, {descending, false}]),
+ {(hd(Res)):id() =:= Id3, "Sort ascending failed"}
end,
fun([Id1, _Id2, _Id3]) ->
- Res = boss_db:find(boss_db_test_model, [], 1, 0, some_text, str_descending),
- {(hd(Res)):id() =:= Id1, "Sort str_descending failed"}
- end,
- fun([Id1, _Id2, _Id3]) ->
- Res = boss_db:find(boss_db_test_model, [], 1, 0, some_integer, num_ascending),
- {(hd(Res)):id() =:= Id1, "Sort num_ascending failed"}
- end,
- fun([_Id1, _Id2, Id3]) ->
- Res = boss_db:find(boss_db_test_model, [], 1, 0, some_integer, num_descending),
- {(hd(Res)):id() =:= Id3, "Sort num_descending failed"}
+ Res = boss_db:find(boss_db_test_model, [], [{limit, 1}, {order_by, some_text}, descending]),
+ {(hd(Res)):id() =:= Id1, "Sort descending failed"}
end,
fun(_) ->
View
34 src/boss_record_compiler.erl
@@ -306,16 +306,16 @@ has_one_forms(HasOne, ModuleName, Opts) ->
erl_syntax:function(erl_syntax:atom(HasOne),
[erl_syntax:clause([], none, [
first_or_undefined_forms(
- has_many_application_forms(Type, ForeignKey, 1, id, str_ascending)
+ has_many_application_forms(Type, ForeignKey, 1, id, false)
)
])]))
].
has_many_forms(HasMany, ModuleName, many, Opts) ->
has_many_forms(HasMany, ModuleName, all, Opts);
has_many_forms(HasMany, ModuleName, Limit, Opts) ->
- Sort = proplists:get_value(sort_by, Opts, 'id'),
- SortOrder = proplists:get_value(sort_order, Opts, str_ascending),
+ Sort = proplists:get_value(order_by, Opts, 'id'),
+ IsDescending = proplists:get_value(descending, Opts, false),
Singular = inflector:singularize(atom_to_list(HasMany)),
Type = proplists:get_value(module, Opts, Singular),
ForeignKey = proplists:get_value(foreign_key, Opts, atom_to_list(ModuleName) ++ "_id"),
@@ -326,7 +326,7 @@ has_many_forms(HasMany, ModuleName, Limit, Opts) ->
"set to the `Id' of this `", ModuleName, "'"])])],
erl_syntax:function(erl_syntax:atom(HasMany),
[erl_syntax:clause([], none, [
- has_many_application_forms(Type, ForeignKey, Limit, Sort, SortOrder)
+ has_many_application_forms(Type, ForeignKey, Limit, Sort, IsDescending)
])])),
erl_syntax:add_precomments([erl_syntax:comment(
[
@@ -336,7 +336,7 @@ has_many_forms(HasMany, ModuleName, Limit, Opts) ->
erl_syntax:function(erl_syntax:atom("first_"++Singular),
[erl_syntax:clause([], none, [
first_or_undefined_forms(
- has_many_application_forms(Type, ForeignKey, 1, Sort, SortOrder)
+ has_many_application_forms(Type, ForeignKey, 1, Sort, IsDescending)
)
])])),
erl_syntax:add_precomments([erl_syntax:comment(
@@ -347,7 +347,7 @@ has_many_forms(HasMany, ModuleName, Limit, Opts) ->
erl_syntax:function(erl_syntax:atom("last_"++Singular),
[erl_syntax:clause([], none, [
first_or_undefined_forms(
- has_many_application_forms(Type, ForeignKey, 1, Sort, reverse_sort_order(SortOrder))
+ has_many_application_forms(Type, ForeignKey, 1, Sort, not IsDescending)
)
])]))
].
@@ -358,12 +358,7 @@ first_or_undefined_forms(Forms) ->
[erl_syntax:variable(?PREFIX++"Record")]),
erl_syntax:clause([erl_syntax:underscore()], none, [erl_syntax:atom(undefined)])]).
-reverse_sort_order(str_ascending) -> str_descending;
-reverse_sort_order(str_descending) -> str_ascending;
-reverse_sort_order(num_ascending) -> num_descending;
-reverse_sort_order(num_descending) -> num_ascending.
-
-has_many_application_forms(Type, ForeignKey, Limit, Sort, SortOrder) ->
+has_many_application_forms(Type, ForeignKey, Limit, Sort, IsDescending) ->
erl_syntax:application(
erl_syntax:atom(?DATABASE_MODULE),
erl_syntax:atom(find),
@@ -373,10 +368,17 @@ has_many_application_forms(Type, ForeignKey, Limit, Sort, SortOrder) ->
erl_syntax:atom(ForeignKey),
erl_syntax:variable("Id")])
]),
- erl_syntax:integer(Limit),
- erl_syntax:integer(0),
- erl_syntax:atom(Sort),
- erl_syntax:atom(SortOrder)
+ erl_syntax:list([
+ erl_syntax:tuple([
+ erl_syntax:atom(limit),
+ erl_syntax:integer(Limit)]),
+ erl_syntax:tuple([
+ erl_syntax:atom(order_by),
+ erl_syntax:atom(Sort)]),
+ erl_syntax:tuple([
+ erl_syntax:atom(descending),
+ erl_syntax:atom(IsDescending)])
+ ])
]).
belongs_to_forms(Type, BelongsTo, ModuleName) ->
View
4 src/db_adapters/boss_db_adapter_mnesia.erl
@@ -88,10 +88,6 @@ apply_sort([], _Key, _Order) ->
[];
apply_sort(List, primary, Order) ->
apply_sort(List, id, Order);
-apply_sort(List, Key, str_ascending) ->
- apply_sort(List, Key, ascending);
-apply_sort(List, Key, str_descending) ->
- apply_sort(List, Key, descending);
apply_sort(List, Key, ascending) ->
Fun = fun (A, B) -> apply(A,Key,[]) =< apply(B,Key,[]) end,
lists:sort(Fun, List);
View
9 src/db_adapters/boss_db_adapter_mongodb.erl
@@ -326,6 +326,8 @@ pack_id(BossId) ->
[]
end.
+unpack_id(_Type, undefined) ->
+ undefined;
unpack_id(Type, MongoId) ->
lists:concat([Type, "-", binary_to_list(dec2hex(element(1, MongoId)))]).
@@ -367,11 +369,8 @@ boss_to_mongo_op('not_in') -> '$nin'.
% Sort clauses
-pack_sort_order(str_ascending) -> 1;
-pack_sort_order(num_ascending) -> 1;
-pack_sort_order(str_descending) -> -1;
-pack_sort_order(num_descending) -> -1.
-
+pack_sort_order(ascending) -> 1;
+pack_sort_order(descending) -> -1.
%%
View
19 src/db_adapters/boss_db_adapter_mysql.erl
@@ -215,14 +215,10 @@ keyindex(Key, N, [Tuple|Rest], Index) ->
_ -> keyindex(Key, N, Rest, Index + 1)
end.
-sort_order_sql(num_ascending) ->
- "ASC";
-sort_order_sql(num_descending) ->
+sort_order_sql(descending) ->
"DESC";
-sort_order_sql(str_ascending) ->
- "ASC";
-sort_order_sql(str_descending) ->
- "DESC".
+sort_order_sql(ascending) ->
+ "ASC".
build_insert_query(Record) ->
Type = element(1, Record),
@@ -253,14 +249,13 @@ build_update_query(Record) ->
{_, TableName, Id} = infer_type_from_id(Record:id()),
Updates = lists:foldl(fun
({id, _}, Acc) -> Acc;
- ({_, undefined}, Acc) -> Acc;
({A, V}, Acc) ->
AString = atom_to_list(A),
- Value = case lists:suffix("_id", AString) of
- true ->
+ Value = case {lists:suffix("_id", AString), V =:= undefined} of
+ {true, false} ->
{_, _, ForeignId} = infer_type_from_id(V),
ForeignId;
- false ->
+ _ ->
V
end,
[AString ++ " = " ++ pack_value(Value)|Acc]
@@ -387,8 +382,6 @@ pack_datetime(DateTime) ->
pack_now(Now) -> pack_datetime(calendar:now_to_datetime(Now)).
-pack_value(false) ->
- "''";
pack_value(undefined) ->
"null";
pack_value(V) when is_binary(V) ->
View
10 src/db_adapters/boss_db_adapter_pgsql.erl
@@ -186,14 +186,10 @@ keyindex(Key, N, [Tuple|Rest], Index) ->
_ -> keyindex(Key, N, Rest, Index + 1)
end.
-sort_order_sql(num_ascending) ->
- "ASC";
-sort_order_sql(num_descending) ->
+sort_order_sql(descending) ->
"DESC";
-sort_order_sql(str_ascending) ->
- "ASC";
-sort_order_sql(str_descending) ->
- "DESC".
+sort_order_sql(ascending) ->
+ "ASC".
build_insert_query(Record) ->
Type = element(1, Record),
View
6 src/db_adapters/boss_db_adapter_riak.erl
@@ -67,10 +67,8 @@ find(Conn, Type, Conditions, Max, Skip, Sort, SortOrder) ->
is_atom(Sort) ->
lists:sort(fun (A, B) ->
case SortOrder of
- num_ascending -> A:Sort() =< B:Sort();
- str_ascending -> A:Sort() =< B:Sort();
- num_descending -> A:Sort() > B:Sort();
- str_descending -> A:Sort() > B:Sort()
+ ascending -> A:Sort() =< B:Sort();
+ descending -> A:Sort() > B:Sort()
end
end,
Records);
View
9 src/db_adapters/boss_db_adapter_tyrant.erl
@@ -39,7 +39,14 @@ find(Conn, Type, Conditions, Max, Skip, Sort, SortOrder) when is_atom(Type), is_
is_integer(Skip), is_atom(Sort), is_atom(SortOrder) ->
case boss_record_lib:ensure_loaded(Type) of
true ->
- Query = build_query(Type, Conditions, Max, Skip, Sort, SortOrder),
+ AttributeTypes = boss_record_lib:attribute_types(Type),
+ TypedSortOrder = case {SortOrder, proplists:get_value(Sort, AttributeTypes)} of
+ {ascending, Type} when Type =:= float; Type =:= integer; Type =:= datetime; Type =:= timestamp -> num_ascending;
+ {descending, Type} when Type =:= float; Type =:= integer; Type =:= datetime; Type =:= timestamp -> num_descending;
+ {ascending, _} -> str_ascending;
+ {descending, _} -> str_descending
+ end,
+ Query = build_query(Type, Conditions, Max, Skip, Sort, TypedSortOrder),
ResultRows = principe_table:mget(Conn, principe_table:search(Conn, Query)),
FilteredRows = case {Max, Skip} of
{all, Skip} when Skip > 0 ->

0 comments on commit b297b50

Please sign in to comment.