Module emysql

The main Emysql module.

Description

The main Emysql module.

Emysql is implemented as an Erlang application. The term has a special meaning in Erlang, see http://www.erlang.org/doc/design_principles/applications.html

This module exports functions to:

  • start and stop the driver (the 'application'),
  • execute queries or prepared statements,
  • prepare such statements,
  • change the connection pool size.
  • Sample

       -module(sample).
       -export([run/0]).
     
       run() ->
     
           crypto:start(),
           emysql:start(),
     
           emysql:add_pool(hello_pool, 1,
               "hello_username", "hello_password", "localhost", 3306,
               "hello_database", utf8),
     
           emysql:execute(hello_pool,
               <<"INSERT INTO hello_table SET hello_text = 'Hello World!'">>),
     
           emysql:prepare(my_stmt, <<"SELECT * from mytable WHERE id = ?">>),
     
           Result = emysql:execute(mypoolname, my_stmt, [1]).

    Implementation

    Under Implementation, you can find details about the inner workings of Emysql. If you are new to Emysql, you may safely ignore them.

    start(), stop(), modules() and default_timeout() are one-line 'fascades':
       start() -> application:start(emysql).
       stop() -> application:stop(emysql).
       modules() -> emysql_app:modules().
       default_timeout() -> emysql_app:default_timeout().
    execute() and prepare() are the bulk of the source of this module. A lot gets repeated for default values in lesser arities. The quintessential execute however is this, in execute/2:
       execute(PoolId, Query, Args, Timeout)
           when (is_list(Query) orelse is_binary(Query)) andalso is_list(Args) andalso is_integer(Timeout) ->
     
               Connection =
                   emysql_conn_mgr:wait_for_connection(PoolId),
                   monitor_work(Connection, Timeout, {emysql_conn, execute, [Connection, Query, Args]});

    As all executions, it uses the monitor_work/3 function to create a process to asynchronously handle the execution.

    The pool-related functions execute brief operations using the primitive functions exported by emysql_conn_mgr and emysql_conn_mgr.

    Data Types

    state()

    state() = any()

    Function Index

    add_pool/2Synchronous call to the connection manager to add a pool.
    add_pool/8Adds a pool using the default start commands (empty list).
    add_pool/9Synchronous call to the connection manager to add a pool.
    affected_rows/1affected_rows/1 extracts the number of affected rows from an OK Packet.
    as_dict/1package row data as a dict.
    as_json/1package row data as erlang json (jsx/jiffy compatible).
    as_proplist/1package row data as a proplist.
    as_record/3Equivalent to as_record(Res, Recname, Fields, fun (A) -> A end).
    as_record/4package row data as records.
    decrement_pool_size/2Synchronous call to the connection manager to shrink a pool.
    default_timeout/0Returns the default timeout in milliseconds.
    execute/2Execute a query, prepared statement or a stored procedure.
    execute/3Execute a query, prepared statement or a stored procedure.
    execute/4Execute a query, prepared statement or a stored procedure.
    execute/5Execute a query, prepared statement or a stored procedure - but return immediately, returning the atom 'unavailable', when no connection in the pool is readily available without wait.
    field_names/1Return the field names of a result packet.
    increment_pool_size/2
    insert_id/1insert_id/1 extracts the Insert ID from an OK Packet.
    prepare/2Prepare a statement.
    remove_pool/1Synchronous call to the connection manager to remove a pool.
    result_type/1result_type/1 decodes a packet into its type.
    start/0Start the Emysql application.
    stop/0Stop the Emysql application.

    Function Details

    add_pool/2

    add_pool(PoolId, Options) -> Result

    Synchronous call to the connection manager to add a pool.

    Options:

    size - pool size (defaults to 1) user - user to connect with (defaults to "") password - user password (defaults to "") host - host to connect to (defaults to "127.0.0.1") port - the port to connect to (defaults to 3306) database - the database to connect to (defaults to undefined) encoding - the connection encoding (defaults to utf8) start_cmds - a list of commands to execute on connect connect_timeout - millisecond timeout for connect or infinity (default)

    Implementation

    Refer to add_pool/8 for implementation details.

    add_pool/8

    add_pool(PoolId, Size, User, Password, Host, Port, Database, Encoding) -> Result

    Equivalent to add_pool(PoolId, Size, User, Password, Host, Port, Database, Encoding, []).

    Adds a pool using the default start commands (empty list).

    add_pool/9

    add_pool(PoolId, Size, User, Password, Host, Port, Database, Encoding, StartCmds) -> Result

    Synchronous call to the connection manager to add a pool.

    Implementation

    Creates a pool record, opens n=Size connections and calls emysql_conn_mgr:add_pool() to make the pool known to the pool management. emysql_conn_mgr:add_pool() is translated into a blocking gen-server call.

    affected_rows/1

    affected_rows(Ok_packet::#ok_packet{}) -> integer()

    affected_rows/1 extracts the number of affected rows from an OK Packet

    as_dict/1

    as_dict(Result) -> Dict

    package row data as a dict

    -module(fetch_example).

    fetch_foo() -> Res = emysql:execute(pool1, "select * from foo"), Res:as_dict(Res).

    as_json/1

    as_json(Res) -> any()

    package row data as erlang json (jsx/jiffy compatible)

    as_proplist/1

    as_proplist(Res::Result) -> proplist

    package row data as a proplist

    -module(fetch_example).

    fetch_foo() -> Res = emysql:execute(pool1, "select * from foo"), Res:as_proplist(Res).

    as_record/3

    as_record(Res, Recname, Fields) -> any()

    Equivalent to as_record(Res, Recname, Fields, fun (A) -> A end).

    as_record/4

    as_record(Res::Result, Recname::RecordName, Fields, Fun) -> Result

    package row data as records

    RecordName is the name of the record to generate. Fields are the field names to generate for each record.

    -module(fetch_example).

    fetch_foo() -> Res = emysql:execute(pool1, "select * from foo"), Res:as_record(foo, record_info(fields, foo)).

    decrement_pool_size/2

    decrement_pool_size(PoolId, Num::By) -> ok

    Synchronous call to the connection manager to shrink a pool.

    This reduces the connections by up to n=By, but it only drops and closes available connections that are not in use at the moment that this function is called. Connections that are waiting for a server response are never dropped. In heavy duty, this function may thus do nothing.

    If 'By' is higher than the amount of connections or the amount of available connections, exactly all available connections are dropped and closed.

    Implementation

    First gets a list of target connections from emysql_conn_mgr:remove_connections(), then relies on emysql_conn:close_connection(Conn) for the proper closing of connections.

    default_timeout/0

    default_timeout() -> Timeout

    Returns the default timeout in milliseconds. As set in emysql.app.src, or if not set, the value ?TIMEOUT as defined in include/emysql.hrl (8000ms).

    Implementation

    src/emysql.app.src is a template for the emysql app file from which ebin/emysql.app is created during building, by a sed command in 'Makefile'.

    execute/2

    execute(PoolId, Query::Query | StmtName) -> Result | [Result]

    Execute a query, prepared statement or a stored procedure.

    Same as execute(PoolId, Query, [], default_timeout()).

    The result is a list for stored procedure execution >= MySQL 4.1

    See also: execute/3, execute/4, execute/5, prepare/2.

    execute/3

    execute(PoolId, Query::Query | StmtName, Args::Args | Timeout) -> Result | [Result]

    Execute a query, prepared statement or a stored procedure.

    Same as execute(PoolId, Query, Args, default_timeout()) or execute(PoolId, Query, [], Timeout).

    Timeout is the query timeout in milliseconds or the atom infinity.

    The result is a list for stored procedure execution >= MySQL 4.1

    See also: execute/2, execute/4, execute/5, prepare/2.

    execute/4

    execute(PoolId, Query::Query | StmtName, Args, Timeout) -> Result | [Result]

    Execute a query, prepared statement or a stored procedure.

  • Opens a connection,
  • sends the query string, or statement atom, and
  • returns the result packet.
  • Basically:
      Connection = emysql_conn_mgr:wait_for_connection(PoolId),
      monitor_work(Connection, Timeout, {emysql_conn, execute, [Connection, Query_or_StmtName, Args]}).

    Timeout is the query timeout in milliseconds or the atom infinity.

    All other execute function eventually call this function.

    See also: execute/2, execute/3, execute/5, prepare/2.

    execute/5

    execute(PoolId, Query::Query | StmtName, Args, Timeout, X5::nonblocking) -> Result | [Result]

    Execute a query, prepared statement or a stored procedure - but return immediately, returning the atom 'unavailable', when no connection in the pool is readily available without wait.

  • Checks if a connection is available,
  • returns 'unavailable' if not,
  • else as the other exception functions(): sends the query string, or statement atom, and
  • returns the result packet.
  • Timeout is the query timeout in milliseconds or the atom infinity.

    Implementation
    Basically:
      {Connection, connection} = case emysql_conn_mgr:lock_connection(PoolId),
           monitor_work(Connection, Timeout, {emysql_conn, execute, [Connection, Query_or_StmtName, Args]}).

    The result is a list for stored procedure execution >= MySQL 4.1

    All other execute function eventually call this function.

    See also: execute/2, execute/3, execute/4, prepare/2.

    field_names/1

    field_names(Result) -> [Name]

    Return the field names of a result packet

    increment_pool_size/2

    increment_pool_size(PoolId::atom(), Num::non_neg_integer()) -> ok | {error, list()}

    insert_id/1

    insert_id(Ok_packet::#ok_packet{}) -> integer() | binary()

    insert_id/1 extracts the Insert ID from an OK Packet

    prepare/2

    prepare(StmtName, Statement) -> ok

    Prepare a statement.

    The atom given by parameter 'StmtName' is bound to the SQL string 'Statement'. Calling execute(<Pool>, StmtName, <ParamList>) executes the statement with parameters from <ParamList>.

    This is not a mySQL prepared statement, but an implementation on the side of Emysql.

    Sample

      -module(sample).
      -export([run/0]).
     
      run() ->
     
       application:start(sasl),
       crypto:start(),
       application:start(emysql),
     
       emysql:add_pool(hello_pool, 1,
           "hello_username", "hello_password", "localhost", 3306,
           "hello_database", utf8),
     
       emysql:execute(hello_pool,
           <<"INSERT INTO hello_table SET hello_text = 'Hello World!'">>),
     
       emysql:prepare(hello_stmt,
           <<"SELECT * from hello_table WHERE hello_text like ?">>),
     
       Result = emysql:execute(hello_pool, hello_stmt, ["Hello%"]),
     
        io:format("~n~s~n", [string:chars($-,72)]),
        io:format("~p~n", [Result]),
     
          ok.
    Output:
      {result_packet,32,
                    [{field,2,<<"def">>,<<"hello_database">>,
                             <<"hello_table">>,<<"hello_table">>,
                             <<"hello_text">>,<<"hello_text">>,254,<<>>,33,
                             60,0,0}],
                     [[<<"Hello World!">>]],
                     <<>>}

    Implementation

    Hands parameters over to emysql_statements:add/2: emysql_statements:add(StmtName, Statement)., which calls handle_call({add, StmtName, Statement}, _From, State).

    The statement is there added to the Emysql statement GB tree: ...
                   State#state{
                       statements = gb_trees:enter(StmtName, {1, Statement},
                           State#state.statements)
    Execution is called like this:
      execute(Connection, StmtName, Args) when is_atom(StmtName), is_list(Args) ->
       prepare_statement(Connection, StmtName),
       case set_params(Connection, 1, Args, undefined) of
           OK when is_record(OK, ok_packet) ->
               ParamNamesBin = list_to_binary(string:join([[$@ | integer_to_list(I)] || I <- lists:seq(1, length(Args))], ", ")),
               StmtNameBin = atom_to_binary(StmtName, utf8),
               Packet = <<?COM_QUERY, "EXECUTE ", StmtNameBin/binary, " USING ", ParamNamesBin/binary>>,
               emysql_tcp:send_and_recv_packet(Connection#emysql_connection.socket, Packet, 0);
           Error ->
               Error
       end.

    See also: emysql_conn:execute/3, emysql_statements:add/2, emysql_statements:handle/3.

    remove_pool/1

    remove_pool(PoolId) -> ok

    Synchronous call to the connection manager to remove a pool.

    Implementation

    Relies on emysql_conn:close_connection(Conn) for the proper closing of connections. Feeds any connection in the pool to it, also the locked ones.

    result_type/1

    result_type(Ok_packet) -> any()

    result_type/1 decodes a packet into its type

    start/0

    start() -> ok

    Start the Emysql application.

    Simply calls application:start(emysql).

    From the Erlang Manual

    If the application is not already loaded, the application controller will first load it using application:load/1. It will check the value of the applications key, to ensure that all applications that should be started before this application are running. The application controller then creates an application master for the application. The application master is the group leader of all the processes in the application. The application master starts the application by calling the application callback function start/2 in the module, and with the start argument, defined by the mod key in the .app file.

    application:start(Application) is the same as calling application:start(Application, temporary). If a temporary application terminates, this is reported but no other applications are terminated.

    See http://www.erlang.org/doc/design_principles/applications.html

    stop/0

    stop() -> ok

    Stop the Emysql application.

    Simply calls application:stop(emysql).

    From the Erlang Manual

    It is always possible to stop an application explicitly by calling application:stop/1. Regardless of the mode, no other applications will be affected.

    See http://www.erlang.org/doc/design_principles/applications.html


    Generated by EDoc, Feb 27 2014, 12:21:24.