# Module emysql

- Description
- Data Types
- Function Index
- Function Details

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

## Function Details

### add_pool/2

`add_pool(PoolId, Options) -> Result`

- `PoolId = atom()`
- `Options = [option()]`
- `option() = {size, integer()} | {user, string()} | {password, string()} | {host, string()} | {port, integer()} | {database, string() | undefined} | {encoding, atom()} | {start_cmds, [binary()]} | {connect_timeout, integer()}`
- `Result = {reply, {error, pool_already_exists}, state()} | {reply, ok, state()}`

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`

- `PoolId = atom()`
- `Size = integer()`
- `User = string()`
- `Password = string()`
- `Host = string()`
- `Port = integer()`
- `Database = string()`
- `Encoding = utf8 | latin1`
- `StartCmds = [binary()]`
- `Result = {reply, {error, pool_already_exists}, state()} | {reply, ok, state()}`

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`

- `Result = #result_packet{}`
- `Dict = 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`

- `Result = #result_packet{}`

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`

- `Result = #result_packet{}`
- `RecordName = atom()`
- `Fields = [atom()]`
- `Fun = function()`
- `Result = [Row]`
- `Row = [record()]`

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`

- `PoolId = atom()`
- `By = integer()`

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`

- `Timeout = integer()`

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]`

- `PoolId = atom()`
- `Query = binary() | string()`
- `StmtName = atom()`
- `Result = ok_packet() | result_packet() | error_packet()`

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]`

- `PoolId = atom()`
- `Query = binary() | string()`
- `StmtName = atom()`
- `Args = [any()]`
- `Timeout = integer() | infinity`
- `Result = ok_packet() | result_packet() | error_packet()`

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]`

- `PoolId = atom()`
- `Query = binary() | string()`
- `StmtName = atom()`
- `Args = [any()]`
- `Timeout = integer() | infinity`
- `Result = ok_packet() | result_packet() | error_packet()`

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]`

- `PoolId = atom()`
- `Query = binary() | string()`
- `StmtName = atom()`
- `Args = [any()]`
- `Timeout = integer() | infinity`
- `Result = ok_packet() | result_packet() | error_packet()`

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]`

- `Result = #result_packet{}`
- `Name = binary()`

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`

- `StmtName = atom()`
- `Statement = binary() | string()`

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`

- `PoolId = atom()`

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.