1
0
mirror of https://github.com/luapower/mysql.git synced 2024-11-12 05:30:17 +01:00
mysql/mysql_client.md
Cosmin Apreutesei ceadb91023 unimportant
2021-04-29 22:47:39 +03:00

247 lines
7.8 KiB
Markdown

## `local mysql = require'mysql_client'`
MySQL client protocol
## Status
This library is considered production ready.
## Example
```lua
local mysql = require "resty.mysql"
local db, err = mysql:new()
if not db then
ngx.say("failed to instantiate mysql: ", err)
return
end
db:set_timeout(1000) -- 1 sec
-- or connect to a unix domain socket file listened
-- by a mysql server:
-- local ok, err, errcode, sqlstate =
-- db:connect{
-- path = "/path/to/mysql.sock",
-- database = "ngx_test",
-- user = "ngx_test",
-- password = "ngx_test" }
local ok, err, errcode, sqlstate = db:connect{
host = "127.0.0.1",
port = 3306,
database = "ngx_test",
user = "ngx_test",
password = "ngx_test",
charset = "utf8",
max_packet_size = 1024 * 1024,
}
if not ok then
ngx.say("failed to connect: ", err, ": ", errcode, " ", sqlstate)
return
end
ngx.say("connected to mysql.")
local res, err, errcode, sqlstate =
db:query("drop table if exists cats")
if not res then
ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
return
end
res, err, errcode, sqlstate =
db:query("create table cats "
.. "(id serial primary key, "
.. "name varchar(5))")
if not res then
ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
return
end
ngx.say("table cats created.")
res, err, errcode, sqlstate =
db:query("insert into cats (name) "
.. "values (\'Bob\'),(\'\'),(null)")
if not res then
ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
return
end
ngx.say(res.affected_rows, " rows inserted into table cats ",
"(last insert id: ", res.insert_id, ")")
-- run a select query, expected about 10 rows in
-- the result set:
res, err, errcode, sqlstate =
db:query("select * from cats order by id asc", 10)
if not res then
ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
return
end
local cjson = require "cjson"
ngx.say("result: ", cjson.encode(res))
-- put it into the connection pool of size 100,
-- with 10 seconds max idle timeout
local ok, err = db:set_keepalive(10000, 100)
if not ok then
ngx.say("failed to set keepalive: ", err)
return
end
-- or just close the connection right away:
-- local ok, err = db:close()
-- if not ok then
-- ngx.say("failed to close: ", err)
-- return
-- end
```
## API
### `mysql:new() -> db | nil,err`
Creates a MySQL connection object.
### `db:connect(options) -> ok | nil,err,errcode,sqlstate`
Connect to a MySQL server.
The `options` argument is a Lua table holding the following keys:
* `host`: the host name for the MySQL server.
* `port`: the port that the MySQL server is listening on. Default to 3306.
* `path`: the path of the unix socket file listened by the MySQL server.
* `database`: the MySQL database name.
* `user`: MySQL account name for login.
* `password`: MySQL account password for login (in clear text).
* `charset`: the character set used for the connection, which can be one of:
`big5`, `dec8`, `cp850`, `hp8`, `koi8r`, `latin1`, `latin2`,
`swe7`, `ascii`, `ujis`, `sjis`, `hebrew`, `tis620`, `euckr`, `koi8u`, `gb2312`, `greek`,
`cp1250`, `gbk`, `latin5`, `armscii8`, `utf8`, `ucs2`, `cp866`, `keybcs2`, `macce`,
`macroman`, `cp852`, `latin7`, `utf8mb4`, `cp1251`, `utf16`, `utf16le`, `cp1256`,
`cp1257`, `utf32`, `binary`, `geostd8`, `cp932`, `eucjpms`, `gb18030`.
* `max_packet_size`: the upper limit for the reply packets sent from the server (default to 1MB).
* `ssl`: if `true`, then uses SSL to connect to MySQL (default to `false`).
If the server does not have SSL support (or just disabled), the error string
"ssl disabled on server" will be returned.
* `ssl_verify`: if `true`, then verifies the validity of the server SSL certificate (default to `false`).
* `compact_arrays`: `true` to use array-of-arrays structure for the result set,
rather than the default array-of-hashes structure.
### `db:set_timeout(time)`
Sets the timeout (in ms) protection for subsequent operations,
including the `connect` method.
### `db:close() -> 1 | nil,err`
Closes the current mysql connection and returns the status.
### `db:send_query(query) -> bytes | nil,err`
Sends the query to the remote MySQL server without waiting for its replies.
Returns the bytes successfully sent out. Use `read_result()` to read the replies.
### `db:read_result([nrows]) -> res | nil,err,errcode,sqlstate`
Reads in one result returned from the server.
It returns a Lua table (`res`) describing the MySQL `OK packet`
or `result set packet` for the query result.
For queries corresponding to a result set, it returns an array holding all the rows.
Each row holds key-value pairs for each data fields. For instance,
```lua
{
{ name = "Bob", age = 32, phone = ngx.null },
{ name = "Marry", age = 18, phone = "10666372"}
}
```
For queries that do not correspond to a result set, it returns a Lua table like this:
```lua
{
insert_id = 0,
server_status = 2,
warning_count = 1,
affected_rows = 32,
message = nil
}
```
If more results are following the current result, a second `err` return value
will be given the string `again`. One should always check this (second) return
value and if it is `again`, then she should call this method again to retrieve
more results. This usually happens when the original query contains multiple
statements (separated by semicolon in the same query string) or calling a
MySQL procedure. See also [Multi-Resultset Support](#multi-resultset-support).
In case of errors, this method returns at most 4 values: `nil`, `err`, `errcode`, and `sqlstate`.
The `err` return value contains a string describing the error, the `errcode`
return value holds the MySQL error code (a numerical value), and finally,
the `sqlstate` return value contains the standard SQL error code that consists
of 5 characters. Note that, the `errcode` and `sqlstate` might be `nil`
if MySQL does not return them.
The optional argument `nrows` can be used to specify an approximate number
of rows for the result set. This value can be used to pre-allocate space
in the resulting Lua table for the result set. By default, it takes the value 4.
### `db:query(query, [nrows]) -> res, err, errcode, sqlstate`
This is a shortcut for combining the [send_query](#send_query) call
and the first [read_result](#read_result) call.
You should always check if the `err` return value is `again` in case of
success because this method will only call [read_result](#read_result)
only once for you. See also [Multi-Resultset Support](#multi-resultset-support).
### `db:server_ver() -> s`
Returns the MySQL server version string, like `"5.1.64"`.
You should only call this method after successfully connecting to a MySQL server,
otherwise `nil` will be returned.
### `db:set_compact_arrays(true|false)`
Sets whether to use the "compact-arrays" structure for the resultsets returned
by subsequent queries. See the `compact_arrays` option for the `connect`
method for more details.
### `mysql.quote(s) -> s`
Quote literal string to be used in queries.
### Multiple result set support
For a SQL query that produces multiple result-sets, it is always your duty to
check the 'again' error message returned by the query, and keep pulling more
result sets by calling the `read_result()` until no 'again' error message
returned (or some other errors happen).
## Limitations
### Authentication
By default, of all authentication methods, only
[Old Password Authentication(mysql_old_password)](https://dev.mysql.com/doc/internals/en/old-password-authentication.html)
and [Secure Password Authentication(mysql_native_password)](https://dev.mysql.com/doc/internals/en/secure-password-authentication.html)
are suppored.
## TODO
* implement the MySQL binary row data packets.
* implement MySQL server prepare and execute packets.
* implement the data compression support in the protocol.