./ct_report/coverage/mongoose_rdbms_mysql.COVER.html

1 %%==============================================================================
2 %% Copyright 2016 Erlang Solutions Ltd.
3 %%
4 %% Licensed under the Apache License, Version 2.0 (the "License");
5 %% you may not use this file except in compliance with the License.
6 %% You may obtain a copy of the License at
7 %%
8 %% http://www.apache.org/licenses/LICENSE-2.0
9 %%
10 %% Unless required by applicable law or agreed to in writing, software
11 %% distributed under the License is distributed on an "AS IS" BASIS,
12 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 %% See the License for the specific language governing permissions and
14 %% limitations under the License.
15 %%==============================================================================
16
17 -module(mongoose_rdbms_mysql).
18 -author('konrad.zemek@erlang-solutions.com').
19 -behaviour(mongoose_rdbms_backend).
20
21 -include("mongoose.hrl").
22
23 -define(MYSQL_PORT, 3306).
24
25 -export([escape_binary/1, unescape_binary/1, connect/2, disconnect/1,
26 query/3, prepare/5, execute/4]).
27
28 %% API
29
30 -spec escape_binary(binary()) -> iodata().
31 escape_binary(Bin) when is_binary(Bin) ->
32
:-(
[<<"X'">>, base16:encode(Bin), <<"'">>].
33
34 -spec unescape_binary(binary()) -> binary().
35 unescape_binary(Bin) when is_binary(Bin) ->
36
:-(
Bin.
37
38 -spec connect(Args :: any(), QueryTimeout :: non_neg_integer()) ->
39 {ok, Connection :: term()} | {error, Reason :: any()}.
40 connect(Settings, QueryTimeout) ->
41
:-(
case mysql:start_link([{query_timeout, QueryTimeout} | db_opts(Settings)]) of
42 {ok, Ref} ->
43
:-(
mysql:query(Ref, <<"set names 'utf8mb4';">>),
44
:-(
mysql:query(Ref, <<"SET SESSION query_cache_type=1;">>),
45
:-(
{ok, Ref};
46 Error ->
47
:-(
Error
48 end.
49
50 -spec disconnect(Connection :: term()) -> any().
51 disconnect(Connection) ->
52
:-(
gen_server:stop(Connection).
53
54 -spec query(Connection :: term(), Query :: any(),
55 Timeout :: infinity | non_neg_integer()) -> mongoose_rdbms:query_result().
56 query(Connection, Query, _Timeout) ->
57
:-(
mysql_to_rdbms(mysql:query(Connection, Query), Connection).
58
59 -spec prepare(Connection :: term(), Name :: atom(), Table :: binary(),
60 Fields :: [binary()], Statement :: iodata()) ->
61 {ok, term()} | {error, any()}.
62 prepare(Connection, Name, _Table, _Fields, Statement) ->
63
:-(
mysql:prepare(Connection, Name, Statement).
64
65 -spec execute(Connection :: term(), StatementRef :: term(), Params :: [term()],
66 Timeout :: infinity | non_neg_integer()) -> mongoose_rdbms:query_result().
67 execute(Connection, StatementRef, Params, _Timeout) ->
68
:-(
Params2 = booleans_as_integers(Params),
69
:-(
mysql_to_rdbms(mysql:execute(Connection, StatementRef, Params2), Connection).
70
71 %% Helpers
72
73 -spec db_opts(Settings :: term()) -> list().
74 db_opts({mysql, Server, DB, User, Pass}) ->
75
:-(
db_opts({mysql, Server, ?MYSQL_PORT, DB, User, Pass});
76 db_opts({mysql, Server, Port, DB, User, Pass}) when is_integer(Port) ->
77
:-(
get_db_basic_opts({Server, Port, DB, User, Pass});
78 db_opts({mysql, Server, DB, User, Pass, SSLConnOpts}) ->
79
:-(
db_opts({mysql, Server, ?MYSQL_PORT, DB, User, Pass, SSLConnOpts});
80 db_opts({mysql, Server, Port, DB, User, Pass, SSLConnOpts})
81 when is_integer(Port) ->
82
:-(
DBBasicOpts = get_db_basic_opts({Server, Port, DB, User, Pass}),
83
:-(
extend_db_opts_with_ssl(DBBasicOpts, SSLConnOpts).
84
85 -spec get_db_basic_opts(Settings :: term()) -> [term()].
86 get_db_basic_opts({Server, Port, DB, User, Pass}) ->
87
:-(
[
88 {host, Server},
89 {port, Port},
90 {user, User},
91 {password, Pass},
92 {database, DB},
93 {found_rows, true}
94 ].
95
96 -spec extend_db_opts_with_ssl(Opts :: [term()], SSLConnOpts :: [term()]) -> [term()].
97 extend_db_opts_with_ssl(Opts, SSLConnOpts) ->
98
:-(
Opts ++ [{ssl, SSLConnOpts}].
99
100 %% @doc Convert MySQL query result to Erlang RDBMS result formalism
101 -spec mysql_to_rdbms(mysql:query_result(), Conn :: term()) -> mongoose_rdbms:query_result().
102 mysql_to_rdbms(ok, Conn) ->
103
:-(
{updated, mysql:affected_rows(Conn)};
104 mysql_to_rdbms({ok, _ColumnNames, Rows}, _Conn) ->
105
:-(
{selected, [list_to_tuple(Row) || Row <- Rows]};
106 mysql_to_rdbms({ok, Results}, Conn) ->
107
:-(
[mysql_to_rdbms({ok, Cols, Rows}, Conn) || {Cols, Rows} <- Results];
108 mysql_to_rdbms({error, {1062, _SQLState, _Message}}, _Conn) ->
109
:-(
{error, duplicate_key};
110 mysql_to_rdbms({error, {_Code, _SQLState, Message}}, _Conn) ->
111
:-(
{error, unicode:characters_to_list(Message)}.
112
113 booleans_as_integers([H|T]) when is_boolean(H) ->
114
:-(
[boolean_to_integer(H)|booleans_as_integers(T)];
115 booleans_as_integers([H|T]) ->
116
:-(
[H|booleans_as_integers(T)];
117 booleans_as_integers([]) ->
118
:-(
[].
119
120
:-(
boolean_to_integer(true) -> 1;
121
:-(
boolean_to_integer(false) -> 0.
Line Hits Source