%%%------------------------------------------------------------------- %%% @author aresei %%% @copyright (C) 2018, %%% @doc %%% %%% @end %%% Created : 29. 九月 2018 17:01 %%%------------------------------------------------------------------- -module(mysql_provider). -author("aresei"). %% API -export([get_row/2, get_row/3, get_all/2, get_all/3]). -export([update/4, update_by/2, update_by/3, insert/4]). %% 从数据库中查找一行记录 -spec get_row(ConnPid :: pid(), Sql::binary()) -> {ok, Record::map()} | undefined. get_row(ConnPid, Sql) when is_pid(ConnPid), is_binary(Sql) -> lager:debug("[mysql_client] get_row sql is: ~p", [Sql]), case mysql:query(ConnPid, Sql) of {ok, Names, [Row | _]} -> {ok, maps:from_list(lists:zip(Names, Row))}; {ok, _, []} -> undefined; Error -> lager:warning("[mysql_client] get error: ~p", [Error]), undefined end. -spec get_row(ConnPid :: pid(), Sql::binary(), Params::list()) -> {ok, Record::map()} | undefined. get_row(ConnPid, Sql, Params) when is_pid(ConnPid), is_binary(Sql), is_list(Params) -> lager:debug("[mysql_client] get_row sql is: ~p, params: ~p", [Sql, Params]), case mysql:query(ConnPid, Sql, Params) of {ok, Names, [Row | _]} -> {ok, maps:from_list(lists:zip(Names, Row))}; {ok, _, []} -> undefined; Error -> lager:warning("[mysql_client] get error: ~p", [Error]), undefined end. -spec get_all(ConnPid :: pid(), Sql::binary()) -> {ok, Rows::list()} | {error, Reason :: any()}. get_all(ConnPid, Sql) when is_pid(ConnPid), is_binary(Sql) -> lager:debug("[mysql_client] get_all sql is: ~p", [Sql]), case mysql:query(ConnPid, Sql) of {ok, Names, Rows} -> {ok, lists:map(fun(Row) -> maps:from_list(lists:zip(Names, Row)) end, Rows)}; {error, Reason} -> lager:warning("[mysql_client] get error: ~p", [Reason]), {error, Reason} end. -spec get_all(ConnPid :: pid(), Sql::binary(), Params::list()) -> {ok, Rows::list()} | {error, Reason::any()}. get_all(ConnPid, Sql, Params) when is_pid(ConnPid), is_binary(Sql), is_list(Params) -> lager:debug("[mysql_client] get_all sql is: ~p, params: ~p", [Sql, Params]), case mysql:query(ConnPid, Sql, Params) of {ok, Names, Rows} -> {ok, lists:map(fun(Row) -> maps:from_list(lists:zip(Names, Row)) end, Rows)}; {error, Reason} -> lager:warning("[mysql_client] get error: ~p", [Reason]), {error, Reason} end. -spec insert(ConnPid :: pid(), Table :: binary(), Fields :: map() | list(), boolean()) -> ok | {ok, InsertId :: integer()} | {error, Reason :: any()}. insert(ConnPid, Table, Fields, FetchInsertId) when is_pid(ConnPid), is_binary(Table), is_map(Fields), is_boolean(FetchInsertId) -> insert(ConnPid, Table, maps:to_list(Fields), FetchInsertId); insert(ConnPid, Table, Fields, FetchInsertId) when is_pid(ConnPid), is_binary(Table), is_list(Fields), is_boolean(FetchInsertId) -> {Keys, Values} = kvs(Fields), FieldSql = iolist_to_binary(lists:join(<<", ">>, Keys)), Placeholders = lists:duplicate(length(Keys), <<"?">>), ValuesPlaceholder = iolist_to_binary(lists:join(<<", ">>, Placeholders)), Sql = <<"INSERT INTO ", Table/binary, "(", FieldSql/binary, ") VALUES(", ValuesPlaceholder/binary, ")">>, lager:debug("[mysql_client] insert sql is: ~p, params: ~p", [Sql, Values]), case mysql:query(ConnPid, Sql, Values) of ok -> case FetchInsertId of true -> InsertId = mysql:insert_id(ConnPid), {ok, InsertId}; false -> ok end; Error -> Error end. -spec update_by(ConnPid :: pid(), UpdateSql :: binary()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}. update_by(ConnPid, UpdateSql) when is_pid(ConnPid), is_binary(UpdateSql) -> lager:debug("[mysql_client] updateBySql sql: ~p", [UpdateSql]), case mysql:query(ConnPid, UpdateSql) of ok -> AffectedRows = mysql:affected_rows(ConnPid), {ok, AffectedRows}; Error -> Error end. -spec update_by(ConnPid :: pid(), UpdateSql :: binary(), Params :: list()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}. update_by(ConnPid, UpdateSql, Params) when is_pid(ConnPid), is_binary(UpdateSql) -> lager:debug("[mysql_client] updateBySql sql: ~p, params: ~p", [UpdateSql, Params]), case mysql:query(ConnPid, UpdateSql, Params) of ok -> AffectedRows = mysql:affected_rows(ConnPid), {ok, AffectedRows}; Error -> Error end. -spec update(ConnPid :: pid(), Sql :: binary(), Fields :: map(), WhereFields :: map()) -> {ok, AffectedRows::integer()} | {error, Reason::any()}. update(ConnPid, Table, Fields, WhereFields) when is_pid(ConnPid), is_binary(Table), is_map(Fields), is_map(WhereFields) -> %% 拼接set {SetKeys, SetVals} = kvs(Fields), SetKeys1 = lists:map(fun(K) when is_binary(K) -> <<"`", K/binary, "` = ?">> end, SetKeys), SetSql = iolist_to_binary(lists:join(<<", ">>, SetKeys1)), %% 拼接where {WhereKeys, WhereVals} = kvs(WhereFields), WhereKeys1 = lists:map(fun(K) when is_binary(K) -> <<"`", K/binary, "` = ?">> end, WhereKeys), WhereSql = iolist_to_binary(lists:join(<<" AND ">>, WhereKeys1)), Params = SetVals ++ WhereVals, Sql = <<"UPDATE ", Table/binary, " SET ", SetSql/binary, " WHERE ", WhereSql/binary>>, lager:debug("[mysql_client] update sql is: ~p, params: ~p", [Sql, Params]), case mysql:query(ConnPid, Sql, Params) of ok -> AffectedRows = mysql:affected_rows(ConnPid), {ok, AffectedRows}; Error -> lager:error("[mysql_client] update sql: ~p, params: ~p, get a error: ~p", [Sql, Params, Error]), Error end. -spec kvs(Fields :: map() | list()) -> {Keys :: list(), Values :: list()}. kvs(Fields) when is_map(Fields) -> kvs(maps:to_list(Fields)); kvs(Fields) when is_list(Fields) -> {Keys0, Values0} = lists:foldl(fun({K, V}, {Acc0, Acc1}) -> {[K|Acc0], [V|Acc1]} end, {[], []}, Fields), {lists:reverse(Keys0), lists:reverse(Values0)}.