small fixes / documentation

This commit is contained in:
Cosmin Apreuetsei 2014-09-10 18:32:38 +03:00
parent 63beb9ab35
commit 439f6bc64f
3 changed files with 70 additions and 47 deletions

View File

@ -1,4 +1,10 @@
--mysql ffi binding (Cosmin Apreutesei, public domain). supports mysql Connector/C 6.1. based on mySQL 5.7 manual.
--mySQL client library ffi binding.
--Written by Cosmin Apreutesei. Public domain.
--Supports mysql Connector/C 6.1.
--Based on mySQL 5.7 manual.
local ffi = require'ffi' local ffi = require'ffi'
local bit = require'bit' local bit = require'bit'
require'mysql_h' require'mysql_h'
@ -22,24 +28,25 @@ end
--error reporting --error reporting
local function myerror(mysql) local function myerror(mysql, stacklevel)
local err = cstring(C.mysql_error(mysql)) local err = cstring(C.mysql_error(mysql))
if not err then return end if not err then return end
error(string.format('mysql error: %s', err)) error(string.format('mysql error: %s', err), stacklevel or 3)
end end
local function checkz(mysql, ret) local function checkz(mysql, ret)
if ret == 0 then return end if ret == 0 then return end
myerror(mysql) myerror(mysql, 4)
end end
local function checkh(mysql, ret) local function checkh(mysql, ret)
if ret ~= NULL then return ret end if ret ~= NULL then return ret end
myerror(mysql) myerror(mysql, 4)
end end
local function enum(e, prefix) local function enum(e, prefix)
return assert(type(e) == 'string' and (prefix and C[prefix..e] or C[e]) or e, 'invalid enum value') local v = type(e) == 'string' and (prefix and C[prefix..e] or C[e]) or e
return assert(v, 'invalid enum value')
end end
--client library info --client library info
@ -582,7 +589,7 @@ local function fetch_row(res, numeric, assoc, decode, field_count, fields, t)
local values = C.mysql_fetch_row(res) local values = C.mysql_fetch_row(res)
if values == NULL then if values == NULL then
if res.conn ~= NULL then --buffered read: check for errors if res.conn ~= NULL then --buffered read: check for errors
myerror(res.conn) myerror(res.conn, 4)
end end
return nil return nil
end end
@ -694,25 +701,25 @@ end
--prepared statements --prepared statements
local function sterror(stmt) local function sterror(stmt, stacklevel)
local err = cstring(C.mysql_stmt_error(stmt)) local err = cstring(C.mysql_stmt_error(stmt))
if not err then return end if not err then return end
error(string.format('mysql error: %s', err)) error(string.format('mysql error: %s', err), stacklevel or 3)
end end
local function stcheckz(stmt, ret) local function stcheckz(stmt, ret)
if ret == 0 then return end if ret == 0 then return end
sterror(stmt) sterror(stmt, 4)
end end
local function stcheckbool(stmt, ret) local function stcheckbool(stmt, ret)
if ret == 1 then return end if ret == 1 then return end
sterror(stmt) sterror(stmt, 4)
end end
local function stcheckh(stmt, ret) local function stcheckh(stmt, ret)
if ret ~= NULL then return ret end if ret ~= NULL then return ret end
sterror(stmt) sterror(stmt, 4)
end end
function conn.prepare(mysql, query) function conn.prepare(mysql, query)
@ -774,11 +781,12 @@ end
function stmt.result_metadata(stmt) function stmt.result_metadata(stmt)
local res = stcheckh(stmt, C.mysql_stmt_result_metadata(stmt)) local res = stcheckh(stmt, C.mysql_stmt_result_metadata(stmt))
return ffi.gc(res, C.mysql_free_result) return res and ffi.gc(res, C.mysql_free_result)
end end
function stmt.fields(stmt) function stmt.fields(stmt)
local res = stmt:result_metadata() local res = stmt:result_metadata()
if not res then return nil end
local fields = res:fields() local fields = res:fields()
return function() return function()
local i, info = fields() local i, info = fields()
@ -1183,6 +1191,7 @@ function stmt.bind_result_types(stmt, maxsize)
local types = {} local types = {}
local field_count = stmt:field_count() local field_count = stmt:field_count()
local res = stmt:result_metadata() local res = stmt:result_metadata()
if not res then return nil end
for i=1,field_count do for i=1,field_count do
local ftype, size, unsigned, decimals = res:field_type(i) local ftype, size, unsigned, decimals = res:field_type(i)
if ftype == 'decimal' then if ftype == 'decimal' then
@ -1199,7 +1208,7 @@ function stmt.bind_result_types(stmt, maxsize)
end end
function stmt.bind_params(stmt, ...) function stmt.bind_params(stmt, ...)
local types = type(...) == 'string' and {...} or ... or {} local types = type((...)) == 'string' and {...} or ... or {}
assert(stmt:param_count() == #types, 'wrong number of param types') assert(stmt:param_count() == #types, 'wrong number of param types')
local bb = params_bind_buffer(types) local bb = params_bind_buffer(types)
stcheckz(stmt, C.mysql_stmt_bind_param(stmt, bb.buffer)) stcheckz(stmt, C.mysql_stmt_bind_param(stmt, bb.buffer))

View File

@ -51,6 +51,7 @@ A complete, lightweight ffi binding of the mysql client library.
`conn:more_results() -> true | false` are there more result sets? `conn:more_results() -> true | false` are there more result sets?
**[Prepared statements]** **[Prepared statements]**
`conn:prepare(query) -> stmt` prepare a query for multiple executions `conn:prepare(query) -> stmt` prepare a query for multiple executions
`stmt:param_count() -> n` number of params
`stmt:exec()` execute a prepared statement `stmt:exec()` execute a prepared statement
`stmt:store_result()` store all the resulted rows to the client `stmt:store_result()` store all the resulted rows to the client
`stmt:fetch() -> true | false | true, 'truncated'` fetch the next row `stmt:fetch() -> true | false | true, 'truncated'` fetch the next row
@ -322,6 +323,10 @@ The flow for prepared statements is like this:
Prepare a query for multiple execution and return a statement object. Prepare a query for multiple execution and return a statement object.
## `stmt:param_count() -> n`
Number of parameters.
## `stmt:exec()` ## `stmt:exec()`
Execute a prepared statement. Execute a prepared statement.

View File

@ -1,5 +1,8 @@
--result of `cpp mysql.h` plus lots of cleanup and defines from other headers; by Cosmin Apreutesei; MySQL Connector/C 6.1
--NOTE that MySQL Connector/C is GPL software. Could this file be considered "derived work" then? --result of `cpp mysql.h` with lots of cleanup and defines from other headers.
--Written by Cosmin Apreutesei. MySQL Connector/C 6.1.
--NOTE: MySQL Connector/C is GPL software. Is this "derived work" then?
local ffi = require'ffi' local ffi = require'ffi'
@ -17,7 +20,7 @@ enum {
MYSQL_DATA_TRUNCATED = 101 MYSQL_DATA_TRUNCATED = 101
}; };
// -------------------------------------------------------------------------------- error constants // ----------------------------------------------------------- error constants
// NOTE: added MYSQL_ prefix to these. // NOTE: added MYSQL_ prefix to these.
enum mysql_error_code { enum mysql_error_code {
@ -88,13 +91,13 @@ enum mysql_error_code {
MYSQL_CR_AUTH_PLUGIN_ERR = 2061 MYSQL_CR_AUTH_PLUGIN_ERR = 2061
}; };
// -------------------------------------------------------------------------------- client library // ------------------------------------------------------------ client library
unsigned int mysql_thread_safe(void); // is the client library thread safe? unsigned int mysql_thread_safe(void); // is the client library thread safe?
const char *mysql_get_client_info(void); const char *mysql_get_client_info(void);
unsigned long mysql_get_client_version(void); unsigned long mysql_get_client_version(void);
// -------------------------------------------------------------------------------- connections // --------------------------------------------------------------- connections
typedef struct MYSQL_ MYSQL; typedef struct MYSQL_ MYSQL;
@ -176,7 +179,8 @@ int mysql_set_character_set(MYSQL *mysql, const char *csname);
int mysql_select_db(MYSQL *mysql, const char *db); int mysql_select_db(MYSQL *mysql, const char *db);
my_bool mysql_change_user(MYSQL *mysql, const char *user, const char *passwd, const char *db); my_bool mysql_change_user(MYSQL *mysql, const char *user, const char *passwd,
const char *db);
my_bool mysql_ssl_set(MYSQL *mysql, const char *key, my_bool mysql_ssl_set(MYSQL *mysql, const char *key,
const char *cert, const char *ca, const char *cert, const char *ca,
@ -189,7 +193,7 @@ enum enum_mysql_set_option
}; };
int mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option); int mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option);
// -------------------------------------------------------------------------------- connection info // ----------------------------------------------------------- connection info
const char * mysql_character_set_name(MYSQL *mysql); const char * mysql_character_set_name(MYSQL *mysql);
@ -215,18 +219,19 @@ unsigned long mysql_get_server_version(MYSQL *mysql);
unsigned int mysql_get_proto_info(MYSQL *mysql); unsigned int mysql_get_proto_info(MYSQL *mysql);
const char * mysql_get_ssl_cipher(MYSQL *mysql); const char * mysql_get_ssl_cipher(MYSQL *mysql);
// -------------------------------------------------------------------------------- transactions // -------------------------------------------------------------- transactions
my_bool mysql_commit(MYSQL * mysql); my_bool mysql_commit(MYSQL * mysql);
my_bool mysql_rollback(MYSQL * mysql); my_bool mysql_rollback(MYSQL * mysql);
my_bool mysql_autocommit(MYSQL * mysql, my_bool auto_mode); my_bool mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
// -------------------------------------------------------------------------------- queries // ------------------------------------------------------------------- queries
unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length); unsigned long mysql_real_escape_string(MYSQL *mysql, char *to,
const char *from, unsigned long length);
int mysql_real_query(MYSQL *mysql, const char *q, unsigned long length); int mysql_real_query(MYSQL *mysql, const char *q, unsigned long length);
// -------------------------------------------------------------------------------- query info // ---------------------------------------------------------------- query info
unsigned int mysql_field_count(MYSQL *mysql); unsigned int mysql_field_count(MYSQL *mysql);
my_ulonglong mysql_affected_rows(MYSQL *mysql); my_ulonglong mysql_affected_rows(MYSQL *mysql);
@ -237,7 +242,7 @@ const char * mysql_sqlstate(MYSQL *mysql);
unsigned int mysql_warning_count(MYSQL *mysql); unsigned int mysql_warning_count(MYSQL *mysql);
const char * mysql_info(MYSQL *mysql); const char * mysql_info(MYSQL *mysql);
// -------------------------------------------------------------------------------- query results // ------------------------------------------------------------- query results
int mysql_next_result(MYSQL *mysql); int mysql_next_result(MYSQL *mysql);
my_bool mysql_more_results(MYSQL *mysql); my_bool mysql_more_results(MYSQL *mysql);
@ -272,7 +277,7 @@ typedef MYSQL_ROWS *MYSQL_ROW_OFFSET;
MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *res); MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *res);
MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset); MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset);
// -------------------------------------------------------------------------------- query field info // ---------------------------------------------------------- query field info
enum enum_field_types { enum enum_field_types {
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
@ -352,13 +357,13 @@ typedef struct st_mysql_field {
MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *res, unsigned int fieldnr); MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *res, unsigned int fieldnr);
// -------------------------------------------------------------------------------- reflection // ---------------------------------------------------------------- reflection
MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild); MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild);
MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild); MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild);
MYSQL_RES *mysql_list_processes(MYSQL *mysql); MYSQL_RES *mysql_list_processes(MYSQL *mysql);
// -------------------------------------------------------------------------------- remote control // ------------------------------------------------------------ remote control
int mysql_kill(MYSQL *mysql, unsigned long pid); int mysql_kill(MYSQL *mysql, unsigned long pid);
@ -403,10 +408,10 @@ enum {
MYSQL_REFRESH_USER_RESOURCES = 0x80000L, MYSQL_REFRESH_USER_RESOURCES = 0x80000L,
MYSQL_REFRESH_FOR_EXPORT = 0x100000L, /* FLUSH TABLES ... FOR EXPORT */ MYSQL_REFRESH_FOR_EXPORT = 0x100000L, /* FLUSH TABLES ... FOR EXPORT */
}; };
int mysql_refresh(MYSQL *mysql, unsigned int refresh_options); // needs RELOAD priviledge int mysql_refresh(MYSQL *mysql, unsigned int refresh_options); // needs RELOAD priviledge
int mysql_dump_debug_info(MYSQL *mysql); // needs SUPER priviledge int mysql_dump_debug_info(MYSQL *mysql); // needs SUPER priviledge
// -------------------------------------------------------------------------------- prepared statements // ------------------------------------------------------- prepared statements
typedef struct MYSQL_STMT_ MYSQL_STMT; typedef struct MYSQL_STMT_ MYSQL_STMT;
@ -461,7 +466,7 @@ my_bool mysql_stmt_send_long_data(MYSQL_STMT *stmt,
const char *data, const char *data,
unsigned long length); unsigned long length);
// -------------------------------------------------------------------------------- prepared statements / bindings // -------------------------------------------- prepared statements / bindings
enum enum_mysql_timestamp_type enum enum_mysql_timestamp_type
{ {
@ -511,7 +516,7 @@ int mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg,
unsigned int column, unsigned int column,
unsigned long offset); unsigned long offset);
// -------------------------------------------------------------------------------- LOAD DATA LOCAL INFILE hooks // ---------------------------------------------- LOAD DATA LOCAL INFILE hooks
void mysql_set_local_infile_handler(MYSQL *mysql, void mysql_set_local_infile_handler(MYSQL *mysql,
int (*local_infile_init)(void **, const char *, void *), int (*local_infile_init)(void **, const char *, void *),
@ -521,31 +526,33 @@ void mysql_set_local_infile_handler(MYSQL *mysql,
void *); void *);
void mysql_set_local_infile_default(MYSQL *mysql); void mysql_set_local_infile_default(MYSQL *mysql);
// -------------------------------------------------------------------------------- mysql proxy scripting // ----------------------------------------------------- mysql proxy scripting
my_bool mysql_read_query_result(MYSQL *mysql); my_bool mysql_read_query_result(MYSQL *mysql);
// -------------------------------------------------------------------------------- debugging // ----------------------------------------------------------------- debugging
void mysql_debug(const char *debug); void mysql_debug(const char *debug);
// -------------------------------------------------------------------------------- present but not documented // ------------------------------------------------ present but not documented
int mysql_server_init(int argc, char **argv, char **groups); int mysql_server_init(int argc, char **argv, char **groups);
void mysql_server_end(void); void mysql_server_end(void);
char *get_tty_password(const char *opt_message); char *get_tty_password(const char *opt_message);
void myodbc_remove_escape(MYSQL *mysql, char *name); void myodbc_remove_escape(MYSQL *mysql, char *name);
my_bool mysql_embedded(void); my_bool mysql_embedded(void);
int mysql_send_query(MYSQL *mysql, const char *q, unsigned long length); int mysql_send_query(MYSQL *mysql, const char *q, unsigned long length);
// -------------------------------------------------------------------------------- redundant functions // ------------------------------------------------------- redundant functions
my_bool mysql_thread_init(void); // called anyway my_bool mysql_thread_init(void); // called anyway
void mysql_thread_end(void); // called anyway void mysql_thread_end(void); // called anyway
const char *mysql_errno_to_sqlstate(unsigned int mysql_errno); // use mysql_sqlstate const char *mysql_errno_to_sqlstate(unsigned int mysql_errno); // use mysql_sqlstate
unsigned long mysql_hex_string(char *to, const char *from, unsigned long from_length); // bad taste unsigned long mysql_hex_string(char *to, const char *from,
unsigned long from_length); // bad taste
// redundant ways to get field info (we use use mysql_field_count and mysql_fetch_field_direct) // redundant ways to get field info.
// we use use mysql_field_count and mysql_fetch_field_direct instead.
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result); MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result);
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res); MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);
typedef unsigned int MYSQL_FIELD_OFFSET; typedef unsigned int MYSQL_FIELD_OFFSET;
@ -553,10 +560,12 @@ MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES *res);
MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset); MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset);
MYSQL_RES *mysql_stmt_param_metadata(MYSQL_STMT *stmt); MYSQL_RES *mysql_stmt_param_metadata(MYSQL_STMT *stmt);
// -------------------------------------------------------------------------------- deprecated functions // ------------------------------------------------------ deprecated functions
unsigned long mysql_escape_string(char *to, const char *from, unsigned long from_length); // use mysql_real_escape_string unsigned long mysql_escape_string(char *to, const char *from,
unsigned long from_length); // use mysql_real_escape_string
int mysql_query(MYSQL *mysql, const char *q); // use mysql_real_query int mysql_query(MYSQL *mysql, const char *q); // use mysql_real_query
MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table, const char *wild); // use "SHOW COLUMNS FROM table" MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table,
const char *wild); // use "SHOW COLUMNS FROM table"
]] ]]