From 5b897017a70b65779b5f3124356b0eae61874501 Mon Sep 17 00:00:00 2001 From: JLarky Date: Thu, 21 Feb 2013 12:04:11 +0400 Subject: [PATCH 01/10] fix https://github.com/Eonblast/Emysql/issues/47 float to binary case --- src/emysql_util.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emysql_util.erl b/src/emysql_util.erl index b182f2df..6066fcde 100644 --- a/src/emysql_util.erl +++ b/src/emysql_util.erl @@ -223,7 +223,7 @@ encode(Val, list, _) when is_float(Val) -> encode(Val, binary, _) when is_float(Val) -> [Res] = io_lib:format("~w", [Val]), - Res; + list_to_binary(Res); encode({datetime, Val}, ReturnType, Encoding) -> encode(Val, ReturnType, Encoding); From 805a9c1dbe81ad5cfe725a1981a19113b22dea3a Mon Sep 17 00:00:00 2001 From: Manuel Rubio Date: Tue, 14 Apr 2015 19:24:16 +0200 Subject: [PATCH 02/10] fix float data --- src/emysql_conn.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emysql_conn.erl b/src/emysql_conn.erl index 01a5c74b..564b86f8 100644 --- a/src/emysql_conn.erl +++ b/src/emysql_conn.erl @@ -427,7 +427,7 @@ encode(Val, binary) when is_integer(Val) -> list_to_binary(integer_to_list(Val)); encode(Val, list) when is_float(Val) -> [Res] = io_lib:format("~w", [Val]), - Res; + list_to_binary(Res); encode(Val, binary) when is_float(Val) -> iolist_to_binary(io_lib:format("~w", [Val])); encode({datetime, Val}, ReturnType) -> From cd00dbb6d4e08cbad16f80de9dd8b2623b476d92 Mon Sep 17 00:00:00 2001 From: Manuel Rubio Date: Fri, 15 May 2015 17:40:06 +0200 Subject: [PATCH 03/10] support for transactions --- README.md | 24 +++++++++++++++++++++++- src/emysql.erl | 18 ++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b603ba72..4698c0fe 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,29 @@ If you are looking for the **plain necessities**, you should use the [ejabberd][ #### Transaction -This driver currently does not support transactions. +This driver supports transaction in this way: + +Usage: + +```erlang +Transaction = fun(Q) -> + R1 = Q(<<"SELECT * from some_table">>, []), + R2 = Q(<<"SELECT * from some_other_table">>, []), + R3 = Q(<"INSERT INTO ...">>, []), + .... + + {ok, SomeResult} +end, + +{ok, Result} = emysql:transaction(Pool, Transaction, Timeout). + +The transaction fun receive one argument, wich is also a function. +That is used to perform queries. Only textual queries allowed +(no prepared statments with arguments). + +The result is the return value of the transaction function. +If the function crashes, transaction is aborted. That is the only +way to abort the transaction: throwing an error. For **mnesia-style transactions**, one of the multiple '[erlang-mysql-driver][22]s' may suite you best. There are [quite many][16] branches of it out there, and they are based on the same project as the ejabberd driver. To learn more about out the differences between the drivers, see the [mysql driver history][History]. diff --git a/src/emysql.erl b/src/emysql.erl index a373de9a..bdee78df 100644 --- a/src/emysql.erl +++ b/src/emysql.erl @@ -110,7 +110,7 @@ %% Used to interact with the database. -export([ prepare/2, - execute/2, execute/3, execute/4, execute/5, + execute/2, execute/3, execute/4, execute/5, transaction/3, default_timeout/0 ]). @@ -533,6 +533,11 @@ execute(PoolId, Query, Timeout) when (is_list(Query) orelse is_binary(Query)) an execute(PoolId, StmtName, Timeout) when is_atom(StmtName), (is_integer(Timeout) orelse Timeout == infinity) -> execute(PoolId, StmtName, [], Timeout). +transaction(PoolId, Fun, Timeout) when is_function(Fun) -> + Connection = emysql_conn_mgr:wait_for_connection(PoolId), + monitor_work(Connection, Timeout, {transaction, Connection, Fun}). + + %% @spec execute(PoolId, Query|StmtName, Args, Timeout) -> Result | [Result] %% PoolId = atom() %% Query = binary() | string() @@ -759,7 +764,16 @@ monitor_work(Connection0, Timeout, Args) when is_record(Connection0, emysql_conn {Pid, Mref} = spawn_monitor( fun() -> put(query_arguments, Args), - Parent ! {self(), apply(fun emysql_conn:execute/3, Args)} + %Parent ! {self(), apply(fun emysql_conn:execute/3, Args)} + case Args of + {transaction, _MaybeOtherConnection, Fun} -> + #ok_packet{} = emysql_conn:execute(Connection, <<"START TRANSACTION;">>, []), + Result = Fun(fun(Query, Params) -> emysql_conn:execute(Connection, Query, Params) end), + #ok_packet{} = emysql_conn:execute(Connection, <<"COMMIT;">>, []), + Parent ! {self(), Result}; + _ -> + Parent ! {self(), apply(fun emysql_conn:execute/3, Args)} + end end), receive {'DOWN', Mref, process, Pid, tcp_connection_closed} -> From 74984e9cd170480cf5ee7e9a53c33058073dcd7e Mon Sep 17 00:00:00 2001 From: Denis Justinek Date: Wed, 29 Jul 2015 10:22:33 +0200 Subject: [PATCH 04/10] Fixed build for Erlang 18.0 - Added Erlang version check and correct type selection - Added erlang:timestamp() check script and correct compilation path for rebar and Makefile - Added macro for TIMESTAMP and replaced direct calls with macros --- include/emysql.hrl | 146 +++++++++++++++++--------------- rebar.config | 2 + rebar.config.script | 14 +++ src/emysql.erl | 18 ++-- src/emysql_conn.erl | 12 +-- src/emysql_conn_mgr.erl | 4 +- support/include.mk | 16 +++- support/ntype_check.escript | 14 +++ support/timestamp_check.escript | 10 +++ 9 files changed, 151 insertions(+), 85 deletions(-) create mode 100644 rebar.config.script create mode 100644 support/ntype_check.escript create mode 100644 support/timestamp_check.escript diff --git a/include/emysql.hrl b/include/emysql.hrl index 1320289f..a036678e 100644 --- a/include/emysql.hrl +++ b/include/emysql.hrl @@ -3,16 +3,16 @@ %% Jacob Vorreuter , %% Henning Diedrich , %% Eonblast Corporation -%% +%% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"),to deal in the Software without restric- -%% tion, including without limitation the rights to use, copy, +%% tion, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell %% copies of the Software, and to permit persons to whom the -%% Software is furnished to do so, subject to the following +%% Software is furnished to do so, subject to the following %% conditions: -%% +%% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% @@ -25,89 +25,104 @@ %% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR %% OTHER DEALINGS IN THE SOFTWARE. - --record(pool, {pool_id :: atom(), - size :: number(), - user :: string(), - password :: string(), - host :: string(), - port :: number(), - database :: string(), +-ifdef(namespaced_types). +-type t_gb_tree() :: gb_trees:tree(). +-type t_queue() :: queue:queue(). +-type t_dict() :: dict:dict(). +-else. +-type t_gb_tree() :: gb_tree(). +-type t_queue() :: queue(). +-type t_dict() :: dict(). +-endif. + +-ifdef(timestamp_support). +-define(TIMESTAMP,erlang:timestamp()). +-else. +-define(TIMESTAMP,erlang:now()). +-endif. + +-record(pool, {pool_id :: atom(), + size :: number(), + user :: string(), + password :: string(), + host :: string(), + port :: number(), + database :: string(), encoding :: utf8 | latin1 | {utf8, utf8_unicode_ci} | {utf8, utf8_general_ci}, - available=queue:new() :: queue(), - locked=gb_trees:empty() :: gb_tree(), - waiting=queue:new() :: queue(), - start_cmds=[] :: string(), - conn_test_period=0 :: number(), + available=queue:new() :: t_queue(), + locked=gb_trees:empty() :: t_gb_tree(), + waiting=queue:new() :: t_queue(), + start_cmds=[] :: string(), + conn_test_period=0 :: number(), connect_timeout=infinity :: number() | infinity, warnings=false :: boolean()}). --record(emysql_connection, {id :: string(), - pool_id :: atom(), +-record(emysql_connection, {id :: string(), + pool_id :: atom(), encoding :: atom(), % maybe could be latin1 | utf8 ? - socket :: inet:socket(), - version :: number(), - thread_id :: number(), - caps :: number(), - language :: number, - prepared=gb_trees:empty(), - locked_at :: number(), - alive=true :: boolean(), - test_period=0 :: number(), - last_test_time=0 :: number(), + socket :: inet:socket(), + version :: number(), + thread_id :: number(), + caps :: number(), + language :: number, + prepared=gb_trees:empty(), + locked_at :: number(), + alive=true :: boolean(), + test_period=0 :: number(), + last_test_time=0 :: number(), monitor_ref :: reference(), warnings=false :: boolean()}). --record(greeting, {protocol_version :: number(), - server_version :: binary(), - thread_id :: number(), - salt1 :: binary(), - salt2 :: binary(), - caps :: number(), - caps_high :: number(), - language :: number(), - status :: number(), - seq_num :: number(), +-record(greeting, {protocol_version :: number(), + server_version :: binary(), + thread_id :: number(), + salt1 :: binary(), + salt2 :: binary(), + caps :: number(), + caps_high :: number(), + language :: number(), + status :: number(), + seq_num :: number(), plugin :: binary()}). --record(field, {seq_num :: number(), - catalog :: binary(), - db :: binary(), - table :: binary(), - org_table :: binary(), - name :: binary(), - org_name :: binary(), - type :: number(), - default :: number(), - charset_nr :: number(), - length :: number(), - flags :: number(), - decimals :: number(), +-record(field, {seq_num :: number(), + catalog :: binary(), + db :: binary(), + table :: binary(), + org_table :: binary(), + name :: binary(), + org_name :: binary(), + type :: number(), + default :: number(), + charset_nr :: number(), + length :: number(), + flags :: number(), + decimals :: number(), decoder :: fun()}). --record(packet, {size :: number(), - seq_num :: number(), +-record(packet, {size :: number(), + seq_num :: number(), data :: binary()}). --record(ok_packet, {seq_num :: number(), - affected_rows :: number(), - insert_id :: number(), - status :: number(), - warning_count :: number(), +-record(ok_packet, {seq_num :: number(), + affected_rows :: number(), + insert_id :: number(), + status :: number(), + warning_count :: number(), msg :: string() | {error, string(), unicode:latin1_chardata() | unicode:chardata() | unicode:external_chardata()} | {incomplete, string(), binary()}}). % It's unfortunate that error_packet's status is binary when the status of other % packets is a number. --record(error_packet, {seq_num :: number(), - code :: number(), - status :: binary(), +-record(error_packet, {seq_num :: number(), + code :: number(), + status :: binary(), msg :: [byte()]}). --record(eof_packet, {seq_num :: number(), - status :: number(), +-record(eof_packet, {seq_num :: number(), + status :: number(), warning_count :: number()}). % extended to mySQL 4.1+ format --record(result_packet, {seq_num :: number(), +-record(result_packet, {seq_num :: number(), field_list :: list(), rows, extra}). @@ -179,4 +194,3 @@ % we discovered that the new statement returns a different % number of result set columns. -define(SERVER_STATUS_METADATA_CHANGED, 1024). - diff --git a/rebar.config b/rebar.config index e61983a8..2b0a7736 100644 --- a/rebar.config +++ b/rebar.config @@ -1,9 +1,11 @@ % -*- Erlang -*- % vim: ts=4 sw=4 et ft=erlang {erl_opts, [ + {platform_define, "^[0-9]+", namespaced_types}, nowarn_deprecated_type ]}. {pre_hooks,[ + {"linux|bsd|darwin|solaris", compile, "escript ./support/crypto_compat.escript"}, {"win32", compile, "escript.exe support/crypto_compat.escript"} ]}. diff --git a/rebar.config.script b/rebar.config.script new file mode 100644 index 00000000..0917d911 --- /dev/null +++ b/rebar.config.script @@ -0,0 +1,14 @@ +{exports, ExportList} = lists:keyfind(exports,1,erlang:module_info()), +Check = lists:member({timestamp,0},ExportList), +case Check of + true -> + case lists:keyfind(erl_opts, 1, CONFIG) of + false -> + CONFIG ++ [{erl_opts,[{d,timestamp_support}]}]; + {erl_opts, Opts} -> + NewOpts = {erl_opts, Opts ++ [{d,timestamp_support}]}, + lists:keyreplace(erl_opts, 1, CONFIG, NewOpts) + end; + false -> + CONFIG +end. diff --git a/src/emysql.erl b/src/emysql.erl index bdee78df..98176849 100644 --- a/src/emysql.erl +++ b/src/emysql.erl @@ -105,9 +105,9 @@ add_pool/9, add_pool/8, remove_pool/1, increment_pool_size/2, decrement_pool_size/2 ]). - + %% Interaction API -%% Used to interact with the database. +%% Used to interact with the database. -export([ prepare/2, execute/2, execute/3, execute/4, execute/5, transaction/3, @@ -246,8 +246,8 @@ config_ok(#pool{pool_id=PoolId,size=Size,user=User,password=Password,host=Host,p config_ok(_BadOptions) -> erlang:error(badarg). -encoding_ok(Enc) when is_atom(Enc) -> ok; -encoding_ok({Enc, Coll}) when is_atom(Enc), is_atom(Coll) -> ok; +encoding_ok(Enc) when is_atom(Enc) -> ok; +encoding_ok({Enc, Coll}) when is_atom(Enc), is_atom(Coll) -> ok; encoding_ok(_) -> erlang:error(badarg). %% Creates a pool record, opens n=Size connections and calls @@ -267,7 +267,7 @@ add_pool(PoolId, Options) when is_list(Options) -> Warnings = proplists:get_value(warnings, Options, false), add_pool(#pool{pool_id=PoolId,size=Size, user=User, password=Password, host=Host, port=Port, database=Database, - encoding=Encoding, start_cmds=StartCmds, + encoding=Encoding, start_cmds=StartCmds, connect_timeout=ConnectTimeout, warnings=Warnings}). add_pool(#pool{pool_id=PoolId,size=Size,user=User,password=Password,host=Host,port=Port, @@ -275,7 +275,7 @@ add_pool(#pool{pool_id=PoolId,size=Size,user=User,password=Password,host=Host,po connect_timeout=ConnectTimeout,warnings=Warnings}=PoolSettings)-> config_ok(PoolSettings), case emysql_conn_mgr:has_pool(PoolId) of - true -> + true -> {error,pool_already_exists}; false -> Pool = #pool{ @@ -328,8 +328,8 @@ add_pool(PoolId, Size, User, Password, Host, Port, Database, Encoding) -> add_pool(PoolId, Size, User, Password, Host, Port, Database, Encoding, StartCmds) -> add_pool(PoolId, Size, User, Password, Host, Port, Database, Encoding, StartCmds, infinity). -add_pool(PoolId, Size, User, Password, Host, Port, Database, - Encoding, StartCmds, ConnectTimeout)-> +add_pool(PoolId, Size, User, Password, Host, Port, Database, + Encoding, StartCmds, ConnectTimeout)-> add_pool(PoolId,[{size,Size},{user,User},{password,Password}, {host,Host},{port,Port},{database,Database}, {encoding,Encoding},{start_cmds,StartCmds}, @@ -674,7 +674,7 @@ result_type(#eof_packet{}) -> eof. -spec as_dict(Result) -> Dict when Result :: #result_packet{}, - Dict :: dict(). + Dict :: t_dict(). as_dict(Res) -> emysql_conv:as_dict(Res). diff --git a/src/emysql_conn.erl b/src/emysql_conn.erl index 564b86f8..26d03e91 100644 --- a/src/emysql_conn.erl +++ b/src/emysql_conn.erl @@ -75,7 +75,7 @@ set_database(Connection, Database) -> set_encoding(_, undefined) -> ok; set_encoding(Connection, {Encoding, Collation}) -> - Packet = <>, emysql_tcp:send_and_recv_packet(Connection#emysql_connection.socket, Packet, 0); set_encoding(Connection, Encoding) -> @@ -260,7 +260,7 @@ run_startcmds_or_die(#emysql_connection{socket=Socket}, StartCmds) -> end, StartCmds ). - + set_encoding_or_die(#emysql_connection { socket = Socket } = Connection, Encoding) -> case set_encoding(Connection, Encoding) of ok -> ok; @@ -269,7 +269,7 @@ set_encoding_or_die(#emysql_connection { socket = Socket } = Connection, Encodin gen_tcp:close(Socket), exit({failed_to_set_encoding, Err2#error_packet.msg}) end. - + reset_connection(Pools, Conn, StayLocked) -> %% if a process dies or times out while doing work %% the socket must be closed and the connection reset @@ -334,7 +334,7 @@ need_test_connection(Conn) -> (Conn#emysql_connection.last_test_time + Conn#emysql_connection.test_period < now_seconds()). now_seconds() -> - {M, S, _} = erlang:now(), + {M, S, _} = ?TIMESTAMP, M * 1000000 + S. %%-------------------------------------------------------------------- @@ -365,7 +365,7 @@ set_params_packet(NumStart, Values) -> BinValues = [encode(Val, binary) || Val <- Values], BinNums = [encode(Num, binary) || Num <- lists:seq(NumStart, NumStart + length(Values) - 1)], BinPairs = lists:zip(BinNums, BinValues), - Parts = [<<"@", NumBin/binary, "=", ValBin/binary>> || {NumBin, ValBin} <- BinPairs], + Parts = [<<"@", NumBin/binary, "=", ValBin/binary>> || {NumBin, ValBin} <- BinPairs], Sets = list_to_binary(join(Parts, <<",">>)), <>. @@ -449,7 +449,7 @@ encode({_Time1, _Time2, _Time3}=Val, binary) -> list_to_binary(encode(Val, list)); encode(Val, _) -> {error, {unrecognized_value, Val}}. - + %% @private two_digits(Nums) when is_list(Nums) -> [two_digits(Num) || Num <- Nums]; diff --git a/src/emysql_conn_mgr.erl b/src/emysql_conn_mgr.erl index b14a08d6..6dc02f11 100644 --- a/src/emysql_conn_mgr.erl +++ b/src/emysql_conn_mgr.erl @@ -40,7 +40,7 @@ -include("emysql.hrl"). --record(state, {pools, lockers = dict:new() :: dict()}). +-record(state, {pools, lockers = dict:new() :: t_dict()}). %%==================================================================== %% API @@ -419,7 +419,7 @@ lock_next_connection(Available ,Locked, Who) -> end. connection_locked_at(Conn, MonitorRef) -> - Conn#emysql_connection{locked_at=lists:nth(2, tuple_to_list(now())), + Conn#emysql_connection{locked_at=lists:nth(2, tuple_to_list(?TIMESTAMP)), monitor_ref = MonitorRef}. serve_waiting_pids(Pool) -> diff --git a/support/include.mk b/support/include.mk index eb826c5a..b6bab0a0 100644 --- a/support/include.mk +++ b/support/include.mk @@ -15,6 +15,19 @@ ifdef debug ERLC_FLAGS += -Ddebug endif +## Check if we are on erlang version that has namespaced types +ERL_NT := $(shell escript ../support/ntype_check.escript) +## Check if we are on erlang version that has erlang:timestamp/0 +ERL_TS := $(shell escript ../support/timestamp_check.escript) + +ifeq ($(ERL_NT),true) + ERLC_FLAGS += -Dnamespaced_types +endif + +ifeq ($(ERL_TS),true) + ERLC_FLAGS += -Dtimestamp_support +endif + EBIN_DIR := ../ebin DOC_DIR := ../doc EMULATOR := beam @@ -30,10 +43,9 @@ EBIN_FILES = $(ERL_OBJECTS) $(APP_FILES:%.app=../ebin/%.app) $(ERL_TEMPLATES) $(EBIN_DIR)/%.$(EMULATOR): %.erl $(ERL_HEADERS) $(ERLC) $(ERLC_FLAGS) -o $(EBIN_DIR) $< -./%.$(EMULATOR): %.erl +./%.$(EMULATOR): %.erl $(ERLC) $(ERLC_FLAGS) -o . $< $(DOC_DIR)/%.html: %.erl $(ERL) -noshell -run edoc file $< -run init stop mv *.html $(DOC_DIR) - diff --git a/support/ntype_check.escript b/support/ntype_check.escript new file mode 100644 index 00000000..eda46d96 --- /dev/null +++ b/support/ntype_check.escript @@ -0,0 +1,14 @@ +#!/usr/bin/env escript +%% vim: ts=4 sw=4 et ft=erlang + +%% The purpose of this script is to check if we need namespaced types for +%% successful compilation. + +main([]) -> + Check = case erlang:system_info(otp_release) of + [X|_] when X >= 48 andalso X =< 57 -> + true; + _ -> + false + end, + io:format("~s",[Check]). diff --git a/support/timestamp_check.escript b/support/timestamp_check.escript new file mode 100644 index 00000000..5c24454a --- /dev/null +++ b/support/timestamp_check.escript @@ -0,0 +1,10 @@ +#!/usr/bin/env escript +%% vim: ts=4 sw=4 et ft=erlang + +%% The purpose of this script is to check if we need namespaced types for +%% successful compilation. + +main([]) -> + {exports, ExportList} = lists:keyfind(exports,1,erlang:module_info()), + Check = lists:member({timestamp,0},ExportList), + io:format("~s",[Check]). From 3ecb481faf6dfb88f8edd0a889c416bc6a41b62e Mon Sep 17 00:00:00 2001 From: Denis Justinek Date: Wed, 29 Jul 2015 11:05:26 +0200 Subject: [PATCH 05/10] Added 18.0 to Travis tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0c3e76c0..a9e52a0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ before_script: script: "make test" otp_release: + - 18.0 - 17.0-rc1 - R16B03-1 - R16B From 2771c87ee536aef5d9b5ff6e6a7cedf75dada3c0 Mon Sep 17 00:00:00 2001 From: Denis Justinek Date: Wed, 29 Jul 2015 11:38:31 +0200 Subject: [PATCH 06/10] Updated Travis config. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a9e52a0c..8aa8d24b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,9 +8,10 @@ before_script: - make script: "make test" + otp_release: - 18.0 - - 17.0-rc1 + - 17.5 - R16B03-1 - R16B - R15B03 From 2de8669d33017249a81e2df8f5dbe567de7ab6f3 Mon Sep 17 00:00:00 2001 From: Denis Justinek Date: Wed, 29 Jul 2015 11:56:28 +0200 Subject: [PATCH 07/10] Fixed tests compilation. --- Makefile | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cd06e0a9..e5d78ed9 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,19 @@ APP_NAME=emysql MODULES=$(shell ls -1 src/*.erl | awk -F[/.] '{ print $$2 }' | sed '$$q;s/$$/,/g') MAKETIME=$(shell date) +## Check if we are on erlang version that has namespaced types +ERL_NT=$(shell escript ./support/ntype_check.escript) + +## Check if we are on erlang version that has erlang:timestamp/0 +ERL_TS=$(shell escript ./support/timestamp_check.escript) + +ifeq ($(ERL_NT),true) +ERLC_NT_FLAG=-Dnamespaced_types +endif +ifeq ($(ERL_TS),true) +ERLC_TS_FLAG=-Dtimestamp_support +endif + all: crypto_compat app (cd src;$(MAKE)) @@ -80,7 +93,7 @@ CT_RUN = ct_run \ CT_SUITES=environment basics conn_mgr build-tests: - erlc -v -o test/ $(wildcard test/*.erl) -pa ebin/ + erlc -v $(ERLC_NT_FLAG) $(ERLC_TS_FLAG) -o test/ $(wildcard test/*.erl) -pa ebin/ test: all build-tests @mkdir -p logs From c7e9ad42e1cc526fcd1060b3452dda9506573fa6 Mon Sep 17 00:00:00 2001 From: Denis Justinek Date: Wed, 26 Aug 2015 21:53:26 +0200 Subject: [PATCH 08/10] Applied patch https://github.com/howleysv/Emysql/commit/dda35e151917c0f43728c15aa4eee98f5aa6e1d3 Moved conditional compilation into .erl files to avoid issues in projects that include emysql header. --- include/emysql.hrl | 22 +++------------------- src/emysql.erl | 19 ++++++++++++++++++- src/emysql_conn.erl | 2 +- src/emysql_conn_mgr.erl | 4 ++-- src/emysql_util.erl | 10 ++++++++++ 5 files changed, 34 insertions(+), 23 deletions(-) diff --git a/include/emysql.hrl b/include/emysql.hrl index a036678e..92157d2b 100644 --- a/include/emysql.hrl +++ b/include/emysql.hrl @@ -25,22 +25,6 @@ %% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR %% OTHER DEALINGS IN THE SOFTWARE. --ifdef(namespaced_types). --type t_gb_tree() :: gb_trees:tree(). --type t_queue() :: queue:queue(). --type t_dict() :: dict:dict(). --else. --type t_gb_tree() :: gb_tree(). --type t_queue() :: queue(). --type t_dict() :: dict(). --endif. - --ifdef(timestamp_support). --define(TIMESTAMP,erlang:timestamp()). --else. --define(TIMESTAMP,erlang:now()). --endif. - -record(pool, {pool_id :: atom(), size :: number(), user :: string(), @@ -49,9 +33,9 @@ port :: number(), database :: string(), encoding :: utf8 | latin1 | {utf8, utf8_unicode_ci} | {utf8, utf8_general_ci}, - available=queue:new() :: t_queue(), - locked=gb_trees:empty() :: t_gb_tree(), - waiting=queue:new() :: t_queue(), + available=queue:new() :: emysql:queue(), + locked=gb_trees:empty() :: emysql:gb_tree(), + waiting=queue:new() :: emysql:queue(), start_cmds=[] :: string(), conn_test_period=0 :: number(), connect_timeout=infinity :: number() | infinity, diff --git a/src/emysql.erl b/src/emysql.erl index 98176849..c70c08b1 100644 --- a/src/emysql.erl +++ b/src/emysql.erl @@ -136,6 +136,23 @@ % for record and constant defines -include("emysql.hrl"). +-export_type([ + gb_tree/0, + queue/0, + dict/0 +]). + +-ifdef(namespaced_types). +-type gb_tree() :: gb_trees:tree(). +-type queue() :: queue:queue(). +-type dict() :: dict:dict(). +-else. +-type gb_tree() :: gb_tree(). +-type queue() :: queue(). +-type dict() :: dict(). +-endif. + + %% @spec start() -> ok %% @doc Start the Emysql application. %% @@ -674,7 +691,7 @@ result_type(#eof_packet{}) -> eof. -spec as_dict(Result) -> Dict when Result :: #result_packet{}, - Dict :: t_dict(). + Dict :: emysql:dict(). as_dict(Res) -> emysql_conv:as_dict(Res). diff --git a/src/emysql_conn.erl b/src/emysql_conn.erl index 26d03e91..c270cc45 100644 --- a/src/emysql_conn.erl +++ b/src/emysql_conn.erl @@ -334,7 +334,7 @@ need_test_connection(Conn) -> (Conn#emysql_connection.last_test_time + Conn#emysql_connection.test_period < now_seconds()). now_seconds() -> - {M, S, _} = ?TIMESTAMP, + {M, S, _} = emysql_util:timestamp(), M * 1000000 + S. %%-------------------------------------------------------------------- diff --git a/src/emysql_conn_mgr.erl b/src/emysql_conn_mgr.erl index 6dc02f11..554a855d 100644 --- a/src/emysql_conn_mgr.erl +++ b/src/emysql_conn_mgr.erl @@ -40,7 +40,7 @@ -include("emysql.hrl"). --record(state, {pools, lockers = dict:new() :: t_dict()}). +-record(state, {pools, lockers = dict:new() :: emysql:dict()}). %%==================================================================== %% API @@ -419,7 +419,7 @@ lock_next_connection(Available ,Locked, Who) -> end. connection_locked_at(Conn, MonitorRef) -> - Conn#emysql_connection{locked_at=lists:nth(2, tuple_to_list(?TIMESTAMP)), + Conn#emysql_connection{locked_at=lists:nth(2, tuple_to_list(emysql_util:timestamp())), monitor_ref = MonitorRef}. serve_waiting_pids(Pool) -> diff --git a/src/emysql_util.erl b/src/emysql_util.erl index 71848cd9..8b0debd1 100644 --- a/src/emysql_util.erl +++ b/src/emysql_util.erl @@ -44,6 +44,11 @@ as_record/4 ]). +%% Erlang version-specific functions +-export([ + timestamp/0 +]). + affected_rows(P) -> emysql:affected_rows(P). field_names(R) -> emysql:field_names(R). insert_id(P) -> emysql:insert_id(P). @@ -55,3 +60,8 @@ as_proplist(Res) -> emysql:as_proplist(Res). as_record(Res, RecName, Fields) -> emysql:as_record(Res, RecName, Fields). as_record(Res, RecName, Fields, Fun) -> emysql:as_record(Res, RecName, Fields, Fun). +-ifdef(timestamp_support). +timestamp() -> erlang:timestamp(). +-else. +timestamp() -> erlang:now(). +-endif. From 16fd0e9cb8e1db2e2fff96baf9f03dacdf4e151b Mon Sep 17 00:00:00 2001 From: Denis Justinek Date: Wed, 26 Aug 2015 21:57:54 +0200 Subject: [PATCH 09/10] Reverted to original state. Builds failed on Erlang prior to 17 --- include/emysql.hrl | 22 +++++++++++++++++++--- src/emysql.erl | 19 +------------------ src/emysql_conn.erl | 2 +- src/emysql_conn_mgr.erl | 4 ++-- src/emysql_util.erl | 10 ---------- 5 files changed, 23 insertions(+), 34 deletions(-) diff --git a/include/emysql.hrl b/include/emysql.hrl index 92157d2b..a036678e 100644 --- a/include/emysql.hrl +++ b/include/emysql.hrl @@ -25,6 +25,22 @@ %% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR %% OTHER DEALINGS IN THE SOFTWARE. +-ifdef(namespaced_types). +-type t_gb_tree() :: gb_trees:tree(). +-type t_queue() :: queue:queue(). +-type t_dict() :: dict:dict(). +-else. +-type t_gb_tree() :: gb_tree(). +-type t_queue() :: queue(). +-type t_dict() :: dict(). +-endif. + +-ifdef(timestamp_support). +-define(TIMESTAMP,erlang:timestamp()). +-else. +-define(TIMESTAMP,erlang:now()). +-endif. + -record(pool, {pool_id :: atom(), size :: number(), user :: string(), @@ -33,9 +49,9 @@ port :: number(), database :: string(), encoding :: utf8 | latin1 | {utf8, utf8_unicode_ci} | {utf8, utf8_general_ci}, - available=queue:new() :: emysql:queue(), - locked=gb_trees:empty() :: emysql:gb_tree(), - waiting=queue:new() :: emysql:queue(), + available=queue:new() :: t_queue(), + locked=gb_trees:empty() :: t_gb_tree(), + waiting=queue:new() :: t_queue(), start_cmds=[] :: string(), conn_test_period=0 :: number(), connect_timeout=infinity :: number() | infinity, diff --git a/src/emysql.erl b/src/emysql.erl index c70c08b1..98176849 100644 --- a/src/emysql.erl +++ b/src/emysql.erl @@ -136,23 +136,6 @@ % for record and constant defines -include("emysql.hrl"). --export_type([ - gb_tree/0, - queue/0, - dict/0 -]). - --ifdef(namespaced_types). --type gb_tree() :: gb_trees:tree(). --type queue() :: queue:queue(). --type dict() :: dict:dict(). --else. --type gb_tree() :: gb_tree(). --type queue() :: queue(). --type dict() :: dict(). --endif. - - %% @spec start() -> ok %% @doc Start the Emysql application. %% @@ -691,7 +674,7 @@ result_type(#eof_packet{}) -> eof. -spec as_dict(Result) -> Dict when Result :: #result_packet{}, - Dict :: emysql:dict(). + Dict :: t_dict(). as_dict(Res) -> emysql_conv:as_dict(Res). diff --git a/src/emysql_conn.erl b/src/emysql_conn.erl index c270cc45..26d03e91 100644 --- a/src/emysql_conn.erl +++ b/src/emysql_conn.erl @@ -334,7 +334,7 @@ need_test_connection(Conn) -> (Conn#emysql_connection.last_test_time + Conn#emysql_connection.test_period < now_seconds()). now_seconds() -> - {M, S, _} = emysql_util:timestamp(), + {M, S, _} = ?TIMESTAMP, M * 1000000 + S. %%-------------------------------------------------------------------- diff --git a/src/emysql_conn_mgr.erl b/src/emysql_conn_mgr.erl index 554a855d..6dc02f11 100644 --- a/src/emysql_conn_mgr.erl +++ b/src/emysql_conn_mgr.erl @@ -40,7 +40,7 @@ -include("emysql.hrl"). --record(state, {pools, lockers = dict:new() :: emysql:dict()}). +-record(state, {pools, lockers = dict:new() :: t_dict()}). %%==================================================================== %% API @@ -419,7 +419,7 @@ lock_next_connection(Available ,Locked, Who) -> end. connection_locked_at(Conn, MonitorRef) -> - Conn#emysql_connection{locked_at=lists:nth(2, tuple_to_list(emysql_util:timestamp())), + Conn#emysql_connection{locked_at=lists:nth(2, tuple_to_list(?TIMESTAMP)), monitor_ref = MonitorRef}. serve_waiting_pids(Pool) -> diff --git a/src/emysql_util.erl b/src/emysql_util.erl index 8b0debd1..71848cd9 100644 --- a/src/emysql_util.erl +++ b/src/emysql_util.erl @@ -44,11 +44,6 @@ as_record/4 ]). -%% Erlang version-specific functions --export([ - timestamp/0 -]). - affected_rows(P) -> emysql:affected_rows(P). field_names(R) -> emysql:field_names(R). insert_id(P) -> emysql:insert_id(P). @@ -60,8 +55,3 @@ as_proplist(Res) -> emysql:as_proplist(Res). as_record(Res, RecName, Fields) -> emysql:as_record(Res, RecName, Fields). as_record(Res, RecName, Fields, Fun) -> emysql:as_record(Res, RecName, Fields, Fun). --ifdef(timestamp_support). -timestamp() -> erlang:timestamp(). --else. -timestamp() -> erlang:now(). --endif. From 1909b7462189db96c2ba7648883c16ffb466720d Mon Sep 17 00:00:00 2001 From: Denis Justinek Date: Thu, 27 Aug 2015 07:05:55 +0200 Subject: [PATCH 10/10] Moved conditional compilation into the .erl files. Included patches: - https://github.com/howleysv/Emysql/commit/dda35e151917c0f43728c15aa4eee98f5aa6e1d3 - https://github.com/howleysv/Emysql/commit/00d2f864d8cea44a7260d1fccf480a8885e16455 --- include/emysql.hrl | 22 +++------------------- src/emysql.erl | 17 +++++++++++++++++ src/emysql_conn.erl | 2 +- src/emysql_conn_mgr.erl | 4 ++-- src/emysql_util.erl | 10 ++++++++++ 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/include/emysql.hrl b/include/emysql.hrl index a036678e..4fa979ba 100644 --- a/include/emysql.hrl +++ b/include/emysql.hrl @@ -25,22 +25,6 @@ %% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR %% OTHER DEALINGS IN THE SOFTWARE. --ifdef(namespaced_types). --type t_gb_tree() :: gb_trees:tree(). --type t_queue() :: queue:queue(). --type t_dict() :: dict:dict(). --else. --type t_gb_tree() :: gb_tree(). --type t_queue() :: queue(). --type t_dict() :: dict(). --endif. - --ifdef(timestamp_support). --define(TIMESTAMP,erlang:timestamp()). --else. --define(TIMESTAMP,erlang:now()). --endif. - -record(pool, {pool_id :: atom(), size :: number(), user :: string(), @@ -49,9 +33,9 @@ port :: number(), database :: string(), encoding :: utf8 | latin1 | {utf8, utf8_unicode_ci} | {utf8, utf8_general_ci}, - available=queue:new() :: t_queue(), - locked=gb_trees:empty() :: t_gb_tree(), - waiting=queue:new() :: t_queue(), + available=queue:new() :: emysql:t_queue(), + locked=gb_trees:empty() :: emysql:t_gb_tree(), + waiting=queue:new() :: emysql:t_queue(), start_cmds=[] :: string(), conn_test_period=0 :: number(), connect_timeout=infinity :: number() | infinity, diff --git a/src/emysql.erl b/src/emysql.erl index 98176849..98c6fe3b 100644 --- a/src/emysql.erl +++ b/src/emysql.erl @@ -136,6 +136,23 @@ % for record and constant defines -include("emysql.hrl"). +-export_type([ + t_gb_tree/0, + t_queue/0, + t_dict/0 +]). + +-ifdef(namespaced_types). +-type t_gb_tree() :: gb_trees:tree(). +-type t_queue() :: queue:queue(). +-type t_dict() :: dict:dict(). +-else. +-type t_gb_tree() :: gb_tree(). +-type t_queue() :: queue(). +-type t_dict() :: dict(). +-endif. + + %% @spec start() -> ok %% @doc Start the Emysql application. %% diff --git a/src/emysql_conn.erl b/src/emysql_conn.erl index 26d03e91..c270cc45 100644 --- a/src/emysql_conn.erl +++ b/src/emysql_conn.erl @@ -334,7 +334,7 @@ need_test_connection(Conn) -> (Conn#emysql_connection.last_test_time + Conn#emysql_connection.test_period < now_seconds()). now_seconds() -> - {M, S, _} = ?TIMESTAMP, + {M, S, _} = emysql_util:timestamp(), M * 1000000 + S. %%-------------------------------------------------------------------- diff --git a/src/emysql_conn_mgr.erl b/src/emysql_conn_mgr.erl index 6dc02f11..8ac8ef26 100644 --- a/src/emysql_conn_mgr.erl +++ b/src/emysql_conn_mgr.erl @@ -40,7 +40,7 @@ -include("emysql.hrl"). --record(state, {pools, lockers = dict:new() :: t_dict()}). +-record(state, {pools, lockers = dict:new() :: emysql:t_dict()}). %%==================================================================== %% API @@ -419,7 +419,7 @@ lock_next_connection(Available ,Locked, Who) -> end. connection_locked_at(Conn, MonitorRef) -> - Conn#emysql_connection{locked_at=lists:nth(2, tuple_to_list(?TIMESTAMP)), + Conn#emysql_connection{locked_at=lists:nth(2, tuple_to_list(emysql_util:timestamp())), monitor_ref = MonitorRef}. serve_waiting_pids(Pool) -> diff --git a/src/emysql_util.erl b/src/emysql_util.erl index 71848cd9..8b0debd1 100644 --- a/src/emysql_util.erl +++ b/src/emysql_util.erl @@ -44,6 +44,11 @@ as_record/4 ]). +%% Erlang version-specific functions +-export([ + timestamp/0 +]). + affected_rows(P) -> emysql:affected_rows(P). field_names(R) -> emysql:field_names(R). insert_id(P) -> emysql:insert_id(P). @@ -55,3 +60,8 @@ as_proplist(Res) -> emysql:as_proplist(Res). as_record(Res, RecName, Fields) -> emysql:as_record(Res, RecName, Fields). as_record(Res, RecName, Fields, Fun) -> emysql:as_record(Res, RecName, Fields, Fun). +-ifdef(timestamp_support). +timestamp() -> erlang:timestamp(). +-else. +timestamp() -> erlang:now(). +-endif.