Skip to content
MySQL Server Protocol in Erlang
Erlang Other
Find file
New pull request


Build Status

MySQL Server Protocol in Erlang. This project let you implement the MySQL protocol for your server. Throught a MySQL connection you could send queries or fake a MySQL connection to do a proxy or whatever else.


The system for tests use maps so, you have to use Erlang OTP 17+.


If you want to use, only add this in rebar.config:

  {deps, [
      {myproto, ".*", {git, "git://", master}}


If you want configure the port, the handler and the server sign:

  {myproto, [
    {handler, my_dummy_handler},
    {parse_query, true},
    {server_sign, <<"5.5-myproto">>},
    {default_storage_engine, <<"myproto">>},
    {port, 3306}

A dummy test

This is a little tutorial to show you the use of this library. As a little introduction, you can create your environment as follow:

mkdir -p mydummy/apps/mydummy
cd mydummy/apps/mydummy
rebar create template=simpleapp appid=mydummy
cd ../..

mkdir rel
cd rel
rebar create template=simplenode nodeid=mydummy
cd ..

Create the file rebar.config as follow:

{sub_dirs, ["apps/*", "rel"]}.
{deps, [
  {myproto, ".*", {git, "git://", master}}

Modify the file rel/files/sys.config as:

 {myproto, [
    {handler, mydummy},
    {parse_query, true},
    {server_sign, <<"5.5-myproto">>},
    {default_storage_engine, <<"myproto">>},
    {port, 3306}

 %% SASL config
 {sasl, [
    {sasl_error_logger, {file, "log/sasl-error.log"}},
    {errlog_type, error},
    {error_logger_mf_dir, "log/sasl"},      % Log directory
    {error_logger_mf_maxbytes, 10485760},   % 10 MB max file size
    {error_logger_mf_maxfiles, 5}           % 5 files max

Now, you can create the apps/mydummy/src/mydummy.erl module:



-export([check_pass/3, metadata/2, execute/2, terminate/2]).

-record(my, {

check_pass(#user{name = User, server_hash = Hash, password = Password}) ->
    case my_request:check_clean_pass(User, Hash) of
        HashedPassword -> {ok, HashedPassword, #my{}};
        _ -> {error, <<"Password incorrect!">>}

metadata(version, State) ->
    {reply, <<"my cool server 1.0">>, State};

metadata({connect_db, Database}, State) ->
    {noreply, State#my{db = Database}};

metadata(databases, State) ->
    {reply, [<<"comet">>], State};

metadata(tables, #db{db = <<"storage">>} = State) ->
    {reply, {<<"storage">>, [<<"channels">>, <<"users">>]}, State};

metadata({fields, <<"channels">> = Table}, #db{db = <<"storage">> = DB} = State) ->
    {reply, {DB, Table, [{name,string},{users_count,integer},{started_at,integer}]}, State};

metadata(_, #my{} = State) ->
    {noreply, State}.

execute(#request{info = 
            #select{params=[#variable{name = <<"version_comment">>}]
        }}, State) ->
    Info = {
        [#column{name = <<"@@version_comment">>, type=?TYPE_VARCHAR, length=20}],
        [[<<"myproto 0.1">>]]
    {reply, #response{status=?STATUS_OK, info=Info}, State};

execute(#request{command = ?COM_QUIT}, State) ->
    lager:info("Exiting~n", []),
    {stop, normal, State};

execute(#request{info = #select{}} = Request, State) ->
    lager:info("Request: ~p~n", [Request]),
    Info = {
            #column{name = <<"Info">>, type=?TYPE_VARCHAR, length=20},
            #column{name = <<"Info2">>, type=?TYPE_VARCHAR, length=20}
            [<<"Not implemented!">>, <<"Yet">>],
            [<<"Testing MultiColumn!">>, <<"Still">>]
    {reply, #response{status=?STATUS_OK, info=Info}, State};

execute(#request{} = Request, State) ->
    lager:info("Unknown request: ~p", [Request]),
    {reply, default, State}. % Return default reply if you don't know answer on this request

terminate(_Reason, _State) ->

Please, mention that dummy module must implement metadata callback, because usually mysql clients ask a lot of information on start about databases, tables and fields in them.

For example, mysql has three different protocols for querying table structure. myproto hides this stuff from you in a very simple and convenient way.

Add this to rel/reltool.config:

    {lib_dirs, ["../apps", "../deps"]},
    {erts, [{mod_cond, derived}, {app_file, strip}]},
    {app_file, strip},
    {rel, "mydummy", "1", [

Now time to build:

rebar get-deps compile generate

And time to launch:

rel/mydummy/bin/mydummy console

Now, to test, in another terminal or shell:

mysql -uroot -proot -h127.0.0.1

You can use some SQL statements as:

SELECT @@version_comment;
SELECT * FROM sometable;

Done :-)

Bitdeli Badge

Something went wrong with that request. Please try again.