ruby mysql module
$Id: mysql.c 250 2010-02-11 10:42:54Z tommy $

include <ruby.h> ifndef RSTRING_PTR define RSTRING_PTR(str) RSTRING(str)->ptr endif ifndef RSTRING_LEN define RSTRING_LEN(str) RSTRING(str)->len endif ifndef RARRAY_PTR define RARRAY_PTR(ary) RARRAY(ary)->ptr endif ifndef HAVE_RB_STR_SET_LEN define rb_str_set_len(str, length) (RSTRING_LEN(str) = (length)) endif

ifdef HAVE_MYSQL_H include <mysql.h> include <errmsg.h> include <mysqld_error.h> else include <mysql/mysql.h> include <mysql/errmsg.h> include <mysql/mysqld_error.h> endif

define MYSQL_RUBY_VERSION 20802

define GC_STORE_RESULT_LIMIT 20

if MYSQL_VERSION_ID < 32224 define mysql_field_count mysql_num_fields endif

define NILorSTRING(obj) (NIL_P(obj)? NULL: StringValuePtr(obj)) define NILorINT(obj) (NIL_P(obj)? 0: NUM2INT(obj))

define GetMysqlStruct(obj) (Check_Type(obj, T_DATA), (struct mysql*)DATA_PTR(obj)) define GetHandler(obj) (Check_Type(obj, T_DATA), &(((struct mysql*)DATA_PTR(obj))->handler)) define GetMysqlRes(obj) (Check_Type(obj, T_DATA), ((struct mysql_res*)DATA_PTR(obj))->res) define GetMysqlStmt(obj) (Check_Type(obj, T_DATA), ((struct mysql_stmt*)DATA_PTR(obj))->stmt)

VALUE cMysql; VALUE cMysqlRes; VALUE cMysqlField; VALUE cMysqlStmt; VALUE cMysqlRowOffset; VALUE cMysqlTime; VALUE eMysql;

static int store_result_count = 0;

struct mysql {

MYSQL handler;
char connection;
char query_with_result;

};

struct mysql_res {

MYSQL_RES* res;
char freed;

};

if MYSQL_VERSION_ID >= 40101 struct mysql_stmt {

MYSQL_STMT *stmt;
char closed;
struct {
    int n;
    MYSQL_BIND *bind;
    unsigned long *length;
    MYSQL_TIME *buffer;
} param;
struct {
    int n;
    MYSQL_BIND *bind;
    my_bool *is_null;
    unsigned long *length;
} result;
MYSQL_RES *res;

}; endif

free Mysql class object

static void free_mysql(struct mysql* my) {

if (my->connection == Qtrue)
    mysql_close(&my->handler);
xfree(my);

}

static void free_mysqlres(struct mysql_res* resp) {

if (resp->freed == Qfalse) {
    mysql_free_result(resp->res);
    store_result_count--;
}
xfree(resp);

}

if MYSQL_VERSION_ID >= 40101 static void free_mysqlstmt_memory(struct mysql_stmt *s) {

if (s->param.bind) {
    xfree(s->param.bind);
    s->param.bind = NULL;
}
if (s->param.length) {
    xfree(s->param.length);
    s->param.length = NULL;
}
if (s->param.buffer) {
    xfree(s->param.buffer);
    s->param.buffer = NULL;
}
s->param.n = 0;
if (s->res) {
    mysql_free_result(s->res);
    s->res = NULL;
}
if (s->result.bind) {
    int i;
    for (i = 0; i < s->result.n; i++) {
        if (s->result.bind[i].buffer)
            xfree(s->result.bind[i].buffer);
        s->result.bind[i].buffer = NULL;
    }
    xfree(s->result.bind);
    s->result.bind = NULL;
}
if (s->result.is_null) {
    xfree(s->result.is_null);
    s->result.is_null = NULL;
}
if (s->result.length) {
    xfree(s->result.length);
    s->result.length = NULL;
}
s->result.n = 0;

}

static void free_execute_memory(struct mysql_stmt *s) {

if (s->res && s->result.bind) {
    int i;
    for (i = 0; i < s->result.n; i++) {
        if (s->result.bind[i].buffer)
            xfree(s->result.bind[i].buffer);
        s->result.bind[i].buffer = NULL;
    }
}
mysql_stmt_free_result(s->stmt);

}

static void free_mysqlstmt(struct mysql_stmt* s) {

free_mysqlstmt_memory(s);
if (s->closed == Qfalse)
    mysql_stmt_close(s->stmt);
if (s->res)
    mysql_free_result(s->res);
xfree(s);

} endif

static void mysql_raise(MYSQL* m) {

VALUE e = rb_exc_new2(eMysql, mysql_error(m));
rb_iv_set(e, "errno", INT2FIX(mysql_errno(m)));

if MYSQL_VERSION_ID >= 40101

rb_iv_set(e, "sqlstate", rb_tainted_str_new2(mysql_sqlstate(m)));

endif

rb_exc_raise(e);

}

static VALUE mysqlres2obj(MYSQL_RES* res) {

VALUE obj;
struct mysql_res* resp;
obj = Data_Make_Struct(cMysqlRes, struct mysql_res, 0, free_mysqlres, resp);
rb_iv_set(obj, "colname", Qnil);
rb_iv_set(obj, "tblcolname", Qnil);
resp->res = res;
resp->freed = Qfalse;
rb_obj_call_init(obj, 0, NULL);
if (++store_result_count > GC_STORE_RESULT_LIMIT)
    rb_gc();
return obj;

}

/* make Mysql::Field object */ static VALUE make_field_obj(MYSQL_FIELD* f) {

VALUE obj;
if (f == NULL)
    return Qnil;
obj = rb_obj_alloc(cMysqlField);
rb_iv_set(obj, "name", f->name? rb_str_freeze(rb_tainted_str_new2(f->name)): Qnil);
rb_iv_set(obj, "table", f->table? rb_str_freeze(rb_tainted_str_new2(f->table)): Qnil);
rb_iv_set(obj, "def", f->def? rb_str_freeze(rb_tainted_str_new2(f->def)): Qnil);
rb_iv_set(obj, "type", INT2NUM(f->type));
rb_iv_set(obj, "length", INT2NUM(f->length));
rb_iv_set(obj, "max_length", INT2NUM(f->max_length));
rb_iv_set(obj, "flags", INT2NUM(f->flags));
rb_iv_set(obj, "decimals", INT2NUM(f->decimals));
return obj;

}

/*——————————-

 Mysql class method
/

/* init() */ static VALUE init(VALUE klass) {

struct mysql* myp;
VALUE obj;

obj = Data_Make_Struct(klass, struct mysql, 0, free_mysql, myp);
mysql_init(&myp->handler);
myp->connection = Qfalse;
myp->query_with_result = Qtrue;
rb_obj_call_init(obj, 0, NULL);
return obj;

}

/* real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) */ static VALUE real_connect(int argc, VALUE* argv, VALUE klass) {

VALUE host, user, passwd, db, port, sock, flag;
char *h, *u, *p, *d, *s;
unsigned int pp, f;
struct mysql* myp;
VALUE obj;

if MYSQL_VERSION_ID >= 32200

rb_scan_args(argc, argv, "07", &host, &user, &passwd, &db, &port, &sock, &flag);
d = NILorSTRING(db);
f = NILorINT(flag);

elif MYSQL_VERSION_ID >= 32115

rb_scan_args(argc, argv, "06", &host, &user, &passwd, &port, &sock, &flag);
f = NILorINT(flag);

else

rb_scan_args(argc, argv, "05", &host, &user, &passwd, &port, &sock);

endif

h = NILorSTRING(host);
u = NILorSTRING(user);
p = NILorSTRING(passwd);
pp = NILorINT(port);
s = NILorSTRING(sock);

ifdef HAVE_RB_THREAD_START_TIMER

rb_thread_stop_timer();

endif

obj = Data_Make_Struct(klass, struct mysql, 0, free_mysql, myp);

if MYSQL_VERSION_ID >= 32200

mysql_init(&myp->handler);
if (mysql_real_connect(&myp->handler, h, u, p, d, pp, s, f) == NULL)

elif MYSQL_VERSION_ID >= 32115

if (mysql_real_connect(&myp->handler, h, u, p, pp, s, f) == NULL)

else

if (mysql_real_connect(&myp->handler, h, u, p, pp, s) == NULL)

endif

{

ifdef HAVE_RB_THREAD_START_TIMER

rb_thread_start_timer();

endif

    mysql_raise(&myp->handler);
}

ifdef HAVE_RB_THREAD_START_TIMER

rb_thread_start_timer();

endif

myp->handler.reconnect = 0;
myp->connection = Qtrue;
myp->query_with_result = Qtrue;
rb_obj_call_init(obj, argc, argv);

return obj;

}

/* escape_string(string) */ static VALUE escape_string(VALUE klass, VALUE str) {

VALUE ret;
Check_Type(str, T_STRING);
ret = rb_str_new(0, (RSTRING_LEN(str))*2+1);
rb_str_set_len(ret, mysql_escape_string(RSTRING_PTR(ret), RSTRING_PTR(str), RSTRING_LEN(str)));
return ret;

}

/* client_info() */ static VALUE client_info(VALUE klass) {

return rb_tainted_str_new2(mysql_get_client_info());

}

if MYSQL_VERSION_ID >= 32332 /* my_debug(string) */ static VALUE my_debug(VALUE obj, VALUE str) {

mysql_debug(StringValuePtr(str));
return obj;

} endif

if MYSQL_VERSION_ID >= 40000 /* client_version() */ static VALUE client_version(VALUE obj) {

return INT2NUM(mysql_get_client_version());

} endif

/*——————————-

 Mysql object method
/

if MYSQL_VERSION_ID >= 32200 /* real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) */ static VALUE real_connect2(int argc, VALUE* argv, VALUE obj) {

VALUE host, user, passwd, db, port, sock, flag;
char *h, *u, *p, *d, *s;
unsigned int pp, f;
MYSQL* m = GetHandler(obj);
rb_scan_args(argc, argv, "07", &host, &user, &passwd, &db, &port, &sock, &flag);
d = NILorSTRING(db);
f = NILorINT(flag);
h = NILorSTRING(host);
u = NILorSTRING(user);
p = NILorSTRING(passwd);
pp = NILorINT(port);
s = NILorSTRING(sock);

ifdef HAVE_RB_THREAD_START_TIMER

rb_thread_stop_timer();

endif

if (mysql_real_connect(m, h, u, p, d, pp, s, f) == NULL) {

ifdef HAVE_RB_THREAD_START_TIMER

rb_thread_start_timer();

endif

    mysql_raise(m);
}

ifdef HAVE_RB_THREAD_START_TIMER

rb_thread_start_timer();

endif

m->reconnect = 0;
GetMysqlStruct(obj)->connection = Qtrue;

return obj;

}

/* options(opt, value=nil) */ static VALUE options(int argc, VALUE* argv, VALUE obj) {

VALUE opt, val;
int n;
my_bool b;
char* v;
MYSQL* m = GetHandler(obj);

rb_scan_args(argc, argv, "11", &opt, &val);
switch(NUM2INT(opt)) {
case MYSQL_OPT_CONNECT_TIMEOUT:

if MYSQL_VERSION_ID >= 40100

case MYSQL_OPT_PROTOCOL:

endif if MYSQL_VERSION_ID >= 40101

case MYSQL_OPT_READ_TIMEOUT:
case MYSQL_OPT_WRITE_TIMEOUT:

endif

    if (val == Qnil)
        rb_raise(rb_eArgError, "wrong # of arguments(1 for 2)");
    n = NUM2INT(val);
    v = (char*)&n;
    break;
case MYSQL_INIT_COMMAND:
case MYSQL_READ_DEFAULT_FILE:
case MYSQL_READ_DEFAULT_GROUP:

if MYSQL_VERSION_ID >= 32349

case MYSQL_SET_CHARSET_DIR:
case MYSQL_SET_CHARSET_NAME:

endif if MYSQL_VERSION_ID >= 40100

case MYSQL_SHARED_MEMORY_BASE_NAME:

endif if MYSQL_VERSION_ID >= 40101

case MYSQL_SET_CLIENT_IP:

endif

if (val == Qnil)
    rb_raise(rb_eArgError, "wrong # of arguments(1 for 2)");
v = StringValuePtr(val);
break;

if MYSQL_VERSION_ID >= 40101

case MYSQL_SECURE_AUTH:
    if (val == Qnil || val == Qfalse)
        b = 1;
    else
        b = 0;
    v = (char*)&b;
    break;

endif if MYSQL_VERSION_ID >= 32349

case MYSQL_OPT_LOCAL_INFILE:
    if (val == Qnil || val == Qfalse)
        v = NULL;
    else {
        n = 1;
        v = (char*)&n;
    }
    break;

endif

default:
    v = NULL;
}

if (mysql_options(m, NUM2INT(opt), v) != 0)
    rb_raise(eMysql, "unknown option: %d", NUM2INT(opt));
return obj;

} endif

if MYSQL_VERSION_ID >= 32332 /* real_escape_string(string) */ static VALUE real_escape_string(VALUE obj, VALUE str) {

MYSQL* m = GetHandler(obj);
VALUE ret;
Check_Type(str, T_STRING);
ret = rb_str_new(0, (RSTRING_LEN(str))*2+1);
rb_str_set_len(ret, mysql_real_escape_string(m, RSTRING_PTR(ret), RSTRING_PTR(str), RSTRING_LEN(str)));
return ret;

} endif

/* initialize() */ static VALUE initialize(int argc, VALUE* argv, VALUE obj) {

return obj;

}

/* affected_rows() */ static VALUE affected_rows(VALUE obj) {

return INT2NUM(mysql_affected_rows(GetHandler(obj)));

}

if MYSQL_VERSION_ID >= 32303 /* change_user(user=nil, passwd=nil, db=nil) */ static VALUE change_user(int argc, VALUE* argv, VALUE obj) {

VALUE user, passwd, db;
char *u, *p, *d;
MYSQL* m = GetHandler(obj);
rb_scan_args(argc, argv, "03", &user, &passwd, &db);
u = NILorSTRING(user);
p = NILorSTRING(passwd);
d = NILorSTRING(db);
if (mysql_change_user(m, u, p, d) != 0)
    mysql_raise(m);
return obj;

} endif

if MYSQL_VERSION_ID >= 32321 /* character_set_name() */ static VALUE character_set_name(VALUE obj) {

return rb_tainted_str_new2(mysql_character_set_name(GetHandler(obj)));

} endif

/* close() */ static VALUE my_close(VALUE obj) {

MYSQL* m = GetHandler(obj);
mysql_close(m);
GetMysqlStruct(obj)->connection = Qfalse;
return obj;

}

if MYSQL_VERSION_ID < 40000 /* create_db(db) */ static VALUE create_db(VALUE obj, VALUE db) {

MYSQL* m = GetHandler(obj);
if (mysql_create_db(m, StringValuePtr(db)) != 0)
    mysql_raise(m);
return obj;

}

/* drop_db(db) */ static VALUE drop_db(VALUE obj, VALUE db) {

MYSQL* m = GetHandler(obj);
if (mysql_drop_db(m, StringValuePtr(db)) != 0)
    mysql_raise(m);
return obj;

} endif

if MYSQL_VERSION_ID >= 32332 /* dump_debug_info() */ static VALUE dump_debug_info(VALUE obj) {

MYSQL* m = GetHandler(obj);
if (mysql_dump_debug_info(m) != 0)
    mysql_raise(m);
return obj;

} endif

/* errno() */ static VALUE my_errno(VALUE obj) {

return INT2NUM(mysql_errno(GetHandler(obj)));

}

/* error() */ static VALUE my_error(VALUE obj) {

return rb_str_new2(mysql_error(GetHandler(obj)));

}

/* field_count() */ static VALUE field_count(VALUE obj) {

return INT2NUM(mysql_field_count(GetHandler(obj)));

}

/* host_info() */ static VALUE host_info(VALUE obj) {

return rb_tainted_str_new2(mysql_get_host_info(GetHandler(obj)));

}

/* proto_info() */ static VALUE proto_info(VALUE obj) {

return INT2NUM(mysql_get_proto_info(GetHandler(obj)));

}

/* server_info() */ static VALUE server_info(VALUE obj) {

return rb_tainted_str_new2(mysql_get_server_info(GetHandler(obj)));

}

/* info() */ static VALUE info(VALUE obj) {

const char* p = mysql_info(GetHandler(obj));
return p? rb_tainted_str_new2(p): Qnil;

}

/* insert_id() */ static VALUE insert_id(VALUE obj) {

return ULL2NUM(mysql_insert_id(GetHandler(obj)));

}

/* kill(pid) */ static VALUE my_kill(VALUE obj, VALUE pid) {

int p = NUM2INT(pid);
MYSQL* m = GetHandler(obj);
if (mysql_kill(m, p) != 0)
    mysql_raise(m);
return obj;

}

/* list_dbs(db=nil) */ static VALUE list_dbs(int argc, VALUE* argv, VALUE obj) {

unsigned int i, n;
VALUE db, ret;
MYSQL* m = GetHandler(obj);
MYSQL_RES* res;

rb_scan_args(argc, argv, "01", &db);
res = mysql_list_dbs(m, NILorSTRING(db));
if (res == NULL)
    mysql_raise(m);

n = mysql_num_rows(res);
ret = rb_ary_new2(n);
for (i=0; i<n; i++)
    rb_ary_store(ret, i, rb_tainted_str_new2(mysql_fetch_row(res)[0]));
mysql_free_result(res);
return ret;

}

/* list_fields(table, field=nil) */ static VALUE list_fields(int argc, VALUE* argv, VALUE obj) {

VALUE table, field;
MYSQL* m = GetHandler(obj);
MYSQL_RES* res;
rb_scan_args(argc, argv, "11", &table, &field);
res = mysql_list_fields(m, StringValuePtr(table), NILorSTRING(field));
if (res == NULL)
    mysql_raise(m);
return mysqlres2obj(res);

}

/* list_processes() */ static VALUE list_processes(VALUE obj) {

MYSQL* m = GetHandler(obj);
MYSQL_RES* res = mysql_list_processes(m);
if (res == NULL)
    mysql_raise(m);
return mysqlres2obj(res);

}

/* list_tables(table=nil) */ static VALUE list_tables(int argc, VALUE* argv, VALUE obj) {

VALUE table;
MYSQL* m = GetHandler(obj);
MYSQL_RES* res;
unsigned int i, n;
VALUE ret;

rb_scan_args(argc, argv, "01", &table);
res = mysql_list_tables(m, NILorSTRING(table));
if (res == NULL)
    mysql_raise(m);

n = mysql_num_rows(res);
ret = rb_ary_new2(n);
for (i=0; i<n; i++)
    rb_ary_store(ret, i, rb_tainted_str_new2(mysql_fetch_row(res)[0]));
mysql_free_result(res);
return ret;

}

/* ping() */ static VALUE ping(VALUE obj) {

MYSQL* m = GetHandler(obj);
if (mysql_ping(m) != 0)
    mysql_raise(m);
return obj;

}

/* refresh® */ static VALUE refresh(VALUE obj, VALUE r) {

MYSQL* m = GetHandler(obj);
if (mysql_refresh(m, NUM2INT(r)) != 0)
    mysql_raise(m);
return obj;

}

/* reload() */ static VALUE reload(VALUE obj) {

MYSQL* m = GetHandler(obj);
if (mysql_reload(m) != 0)
    mysql_raise(m);
return obj;

}

/* select_db(db) */ static VALUE select_db(VALUE obj, VALUE db) {

MYSQL* m = GetHandler(obj);
if (mysql_select_db(m, StringValuePtr(db)) != 0)
    mysql_raise(m);
return obj;

}

/* shutdown() */ static VALUE my_shutdown(int argc, VALUE* argv, VALUE obj) {

MYSQL* m = GetHandler(obj);
VALUE level;

rb_scan_args(argc, argv, "01", &level);

if MYSQL_VERSION_ID >= 40103

if (mysql_shutdown(m, NIL_P(level) ? SHUTDOWN_DEFAULT : NUM2INT(level)) != 0)

else

if (mysql_shutdown(m) != 0)

endif

    mysql_raise(m);
return obj;

}

/* stat() */ static VALUE my_stat(VALUE obj) {

MYSQL* m = GetHandler(obj);
const char* s = mysql_stat(m);
if (s == NULL)
    mysql_raise(m);
return rb_tainted_str_new2(s);

}

/* store_result() */ static VALUE store_result(VALUE obj) {

MYSQL* m = GetHandler(obj);
MYSQL_RES* res = mysql_store_result(m);
if (res == NULL)
    mysql_raise(m);
return mysqlres2obj(res);

}

/* thread_id() */ static VALUE thread_id(VALUE obj) {

return INT2NUM(mysql_thread_id(GetHandler(obj)));

}

/* use_result() */ static VALUE use_result(VALUE obj) {

MYSQL* m = GetHandler(obj);
MYSQL_RES* res = mysql_use_result(m);
if (res == NULL)
    mysql_raise(m);
return mysqlres2obj(res);

}

static VALUE res_free(VALUE); /* query(sql) */ static VALUE query(VALUE obj, VALUE sql) {

int loop = 0;
MYSQL* m = GetHandler(obj);
Check_Type(sql, T_STRING);
if (GetMysqlStruct(obj)->connection == Qfalse) {
    rb_raise(eMysql, "query: not connected");
}
if (rb_block_given_p()) {
    if (mysql_real_query(m, RSTRING_PTR(sql), RSTRING_LEN(sql)) != 0)
        mysql_raise(m);
    do {
        MYSQL_RES* res = mysql_store_result(m);
        if (res == NULL) {
            if (mysql_field_count(m) != 0)
                mysql_raise(m);
        } else {
            VALUE robj = mysqlres2obj(res);
            rb_ensure(rb_yield, robj, res_free, robj);
        }

if MYSQL_VERSION_ID >= 40101

    if ((loop = mysql_next_result(m)) > 0)
        mysql_raise(m);
} while (loop == 0);

else

} while (0);

endif

    return obj;
}
if (mysql_real_query(m, RSTRING_PTR(sql), RSTRING_LEN(sql)) != 0)
    mysql_raise(m);
if (GetMysqlStruct(obj)->query_with_result == Qfalse)
    return obj;
if (mysql_field_count(m) == 0)
    return Qnil;
return store_result(obj);

}

if MYSQL_VERSION_ID >= 40100 /* server_version() */ static VALUE server_version(VALUE obj) {

return INT2NUM(mysql_get_server_version(GetHandler(obj)));

}

/* warning_count() */ static VALUE warning_count(VALUE obj) {

return INT2NUM(mysql_warning_count(GetHandler(obj)));

}

/* commit() */ static VALUE commit(VALUE obj) {

MYSQL* m = GetHandler(obj);
if (mysql_commit(m) != 0)
    mysql_raise(m);
return obj;

}

/* rollback() */ static VALUE rollback(VALUE obj) {

MYSQL* m = GetHandler(obj);
if (mysql_rollback(m) != 0)
    mysql_raise(m);
return obj;

}

/* autocommit() */ static VALUE autocommit(VALUE obj, VALUE mode) {

MYSQL* m = GetHandler(obj);
int f;
f = (mode == Qnil || mode == Qfalse || (rb_type(mode) == T_FIXNUM && NUM2INT(mode) == 0)) ? 0 : 1;
if (mysql_autocommit(m, f) != 0)
    mysql_raise(m);
return obj;

} endif

ifdef HAVE_MYSQL_SSL_SET /* ssl_set(key=nil, cert=nil, ca=nil, capath=nil, cipher=nil) */ static VALUE ssl_set(int argc, VALUE* argv, VALUE obj) {

VALUE key, cert, ca, capath, cipher;
char *s_key, *s_cert, *s_ca, *s_capath, *s_cipher;
MYSQL* m = GetHandler(obj);
rb_scan_args(argc, argv, "05", &key, &cert, &ca, &capath, &cipher);
s_key = NILorSTRING(key);
s_cert = NILorSTRING(cert);
s_ca = NILorSTRING(ca);
s_capath = NILorSTRING(capath);
s_cipher = NILorSTRING(cipher);
mysql_ssl_set(m, s_key, s_cert, s_ca, s_capath, s_cipher);
return obj;

} endif

if MYSQL_VERSION_ID >= 40100 /* more_results() */ static VALUE more_results(VALUE obj) {

if (mysql_more_results(GetHandler(obj)) == 0)
    return Qfalse;
else
    return Qtrue;

}

static VALUE next_result(VALUE obj) {

MYSQL* m = GetHandler(obj);
int ret;
ret = mysql_next_result(m);
if (ret > 0)
    mysql_raise(m);
if (ret == 0)
    return Qtrue;
return Qfalse;

} endif

if MYSQL_VERSION_ID >= 40101 /* set_server_option(option) */ static VALUE set_server_option(VALUE obj, VALUE option) {

MYSQL *m = GetHandler(obj);
if (mysql_set_server_option(m, NUM2INT(option)) != 0)
    mysql_raise(m);
return obj;

}

/* sqlstate() */ static VALUE sqlstate(VALUE obj) {

MYSQL *m = GetHandler(obj);
return rb_tainted_str_new2(mysql_sqlstate(m));

} endif

if MYSQL_VERSION_ID >= 40102 /* stmt_init() */ static VALUE stmt_init(VALUE obj) {

MYSQL *m = GetHandler(obj);
MYSQL_STMT *s;
struct mysql_stmt* stmt;
my_bool true = 1;
VALUE st_obj;

if ((s = mysql_stmt_init(m)) == NULL)
    mysql_raise(m);
if (mysql_stmt_attr_set(s, STMT_ATTR_UPDATE_MAX_LENGTH, &true))
    rb_raise(rb_eArgError, "mysql_stmt_attr_set() failed");
st_obj = Data_Make_Struct(cMysqlStmt, struct mysql_stmt, 0, free_mysqlstmt, stmt);
memset(stmt, 0, sizeof(*stmt));
stmt->stmt = s;
stmt->closed = Qfalse;
return st_obj;

}

static VALUE stmt_prepare(VALUE obj, VALUE query); /* prepare(query) */ static VALUE prepare(VALUE obj, VALUE query) {

VALUE st;
st = stmt_init(obj);
return stmt_prepare(st, query);

} endif

/* query_with_result() */ static VALUE query_with_result(VALUE obj) {

return GetMysqlStruct(obj)->query_with_result? Qtrue: Qfalse;

}

/* query_with_result=(flag) */ static VALUE query_with_result_set(VALUE obj, VALUE flag) {

if (TYPE(flag) != T_TRUE && TYPE(flag) != T_FALSE)
    rb_raise(rb_eTypeError, "invalid type, required true or false.");
GetMysqlStruct(obj)->query_with_result = flag;
return flag;

}

/* reconnect() */ static VALUE reconnect(VALUE obj) {

return GetHandler(obj)->reconnect ? Qtrue : Qfalse;

}

/* reconnect=(flag) */ static VALUE reconnect_set(VALUE obj, VALUE flag) {

GetHandler(obj)->reconnect = (flag == Qnil || flag == Qfalse) ? 0 : 1;
return flag;

}

/*——————————-

 Mysql::Result object method
/

/* check if already freed */ static void check_free(VALUE obj) {

struct mysql_res* resp = DATA_PTR(obj);
if (resp->freed == Qtrue)
    rb_raise(eMysql, "Mysql::Result object is already freed");

}

/* data_seek(offset) */ static VALUE data_seek(VALUE obj, VALUE offset) {

check_free(obj);
mysql_data_seek(GetMysqlRes(obj), NUM2INT(offset));
return obj;

}

/* fetch_field() */ static VALUE fetch_field(VALUE obj) {

check_free(obj);
return make_field_obj(mysql_fetch_field(GetMysqlRes(obj)));

}

/* fetch_fields() */ static VALUE fetch_fields(VALUE obj) {

MYSQL_RES* res;
MYSQL_FIELD* f;
unsigned int n;
VALUE ret;
unsigned int i;
check_free(obj);
res = GetMysqlRes(obj);
f = mysql_fetch_fields(res);
n = mysql_num_fields(res);
ret = rb_ary_new2(n);
for (i=0; i<n; i++)
    rb_ary_store(ret, i, make_field_obj(&f[i]));
return ret;

}

/* fetch_field_direct(nr) */ static VALUE fetch_field_direct(VALUE obj, VALUE nr) {

MYSQL_RES* res;
unsigned int max;
unsigned int n;
check_free(obj);
res = GetMysqlRes(obj);
max = mysql_num_fields(res);
n = NUM2INT(nr);
if (n >= max)
    rb_raise(eMysql, "%d: out of range (max: %d)", n, max-1);

if MYSQL_VERSION_ID >= 32226

return make_field_obj(mysql_fetch_field_direct(res, n));

else

return make_field_obj(&mysql_fetch_field_direct(res, n));

endif }

/* fetch_lengths() */ static VALUE fetch_lengths(VALUE obj) {

MYSQL_RES* res;
unsigned int n;
unsigned long* lengths;
VALUE ary;
unsigned int i;
check_free(obj);
res = GetMysqlRes(obj);
n = mysql_num_fields(res);
lengths = mysql_fetch_lengths(res);
if (lengths == NULL)
    return Qnil;
ary = rb_ary_new2(n);
for (i=0; i<n; i++)
    rb_ary_store(ary, i, INT2NUM(lengths[i]));
return ary;

}

/* fetch_row() */ static VALUE fetch_row(VALUE obj) {

MYSQL_RES* res;
unsigned int n;
MYSQL_ROW row;
unsigned long* lengths;
VALUE ary;
unsigned int i;
check_free(obj);
res = GetMysqlRes(obj);
n = mysql_num_fields(res);
row = mysql_fetch_row(res);
lengths = mysql_fetch_lengths(res);
if (row == NULL)
    return Qnil;
ary = rb_ary_new2(n);
for (i=0; i<n; i++)
    rb_ary_store(ary, i, row[i]? rb_tainted_str_new(row[i], lengths[i]): Qnil);
return ary;

}

/* fetch_hash2 (internal) */ static VALUE fetch_hash2(VALUE obj, VALUE with_table) {

MYSQL_RES* res = GetMysqlRes(obj);
unsigned int n = mysql_num_fields(res);
MYSQL_ROW row = mysql_fetch_row(res);
unsigned long* lengths = mysql_fetch_lengths(res);
MYSQL_FIELD* fields = mysql_fetch_fields(res);
unsigned int i;
VALUE hash;
VALUE colname;
if (row == NULL)
    return Qnil;
hash = rb_hash_new();

if (with_table == Qnil || with_table == Qfalse) {
    colname = rb_iv_get(obj, "colname");
    if (colname == Qnil) {
        colname = rb_ary_new2(n);
        for (i=0; i<n; i++) {
            VALUE s = rb_tainted_str_new2(fields[i].name);
            rb_obj_freeze(s);
            rb_ary_store(colname, i, s);
        }
        rb_obj_freeze(colname);
        rb_iv_set(obj, "colname", colname);
    }
} else {
    colname = rb_iv_get(obj, "tblcolname");
    if (colname == Qnil) {
        colname = rb_ary_new2(n);
        for (i=0; i<n; i++) {
            int len = strlen(fields[i].table)+strlen(fields[i].name)+1;
            VALUE s = rb_tainted_str_new(NULL, len);
            snprintf(RSTRING_PTR(s), len+1, "%s.%s", fields[i].table, fields[i].name);
            rb_obj_freeze(s);
            rb_ary_store(colname, i, s);
        }
        rb_obj_freeze(colname);
        rb_iv_set(obj, "tblcolname", colname);
    }
}
for (i=0; i<n; i++) {
    rb_hash_aset(hash, rb_ary_entry(colname, i), row[i]? rb_tainted_str_new(row[i], lengths[i]): Qnil);
}
return hash;

}

/* fetch_hash(with_table=false) */ static VALUE fetch_hash(int argc, VALUE* argv, VALUE obj) {

VALUE with_table;
check_free(obj);
rb_scan_args(argc, argv, "01", &with_table);
if (with_table == Qnil)
    with_table = Qfalse;
return fetch_hash2(obj, with_table);

}

/* field_seek(offset) */ static VALUE field_seek(VALUE obj, VALUE offset) {

check_free(obj);
return INT2NUM(mysql_field_seek(GetMysqlRes(obj), NUM2INT(offset)));

}

/* field_tell() */ static VALUE field_tell(VALUE obj) {

check_free(obj);
return INT2NUM(mysql_field_tell(GetMysqlRes(obj)));

}

/* free() */ static VALUE res_free(VALUE obj) {

struct mysql_res* resp = DATA_PTR(obj);
check_free(obj);
mysql_free_result(resp->res);
resp->freed = Qtrue;
store_result_count--;
return Qnil;

}

/* num_fields() */ static VALUE num_fields(VALUE obj) {

check_free(obj);
return INT2NUM(mysql_num_fields(GetMysqlRes(obj)));

}

/* num_rows() */ static VALUE num_rows(VALUE obj) {

check_free(obj);
return INT2NUM(mysql_num_rows(GetMysqlRes(obj)));

}

/* row_seek(offset) */ static VALUE row_seek(VALUE obj, VALUE offset) {

MYSQL_ROW_OFFSET prev_offset;
if (CLASS_OF(offset) != cMysqlRowOffset)
    rb_raise(rb_eTypeError, "wrong argument type %s (expected Mysql::RowOffset)", rb_obj_classname(offset));
check_free(obj);
prev_offset = mysql_row_seek(GetMysqlRes(obj), DATA_PTR(offset));
return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, prev_offset);

}

/* row_tell() */ static VALUE row_tell(VALUE obj) {

MYSQL_ROW_OFFSET offset;
check_free(obj);
offset = mysql_row_tell(GetMysqlRes(obj));
return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, offset);

}

/* each {…} */ static VALUE each(VALUE obj) {

VALUE row;
check_free(obj);
while ((row = fetch_row(obj)) != Qnil)
    rb_yield(row);
return obj;

}

/* each_hash(with_table=false) {…} */ static VALUE each_hash(int argc, VALUE* argv, VALUE obj) {

VALUE with_table;
VALUE hash;
check_free(obj);
rb_scan_args(argc, argv, "01", &with_table);
if (with_table == Qnil)
    with_table = Qfalse;
while ((hash = fetch_hash2(obj, with_table)) != Qnil)
    rb_yield(hash);
return obj;

}

/*——————————-

 Mysql::Field object method
/

/* hash */ static VALUE field_hash(VALUE obj) {

VALUE h = rb_hash_new();
rb_hash_aset(h, rb_str_new2("name"), rb_iv_get(obj, "name"));
rb_hash_aset(h, rb_str_new2("table"), rb_iv_get(obj, "table"));
rb_hash_aset(h, rb_str_new2("def"), rb_iv_get(obj, "def"));
rb_hash_aset(h, rb_str_new2("type"), rb_iv_get(obj, "type"));
rb_hash_aset(h, rb_str_new2("length"), rb_iv_get(obj, "length"));
rb_hash_aset(h, rb_str_new2("max_length"), rb_iv_get(obj, "max_length"));
rb_hash_aset(h, rb_str_new2("flags"), rb_iv_get(obj, "flags"));
rb_hash_aset(h, rb_str_new2("decimals"), rb_iv_get(obj, "decimals"));
return h;

}

/* inspect */ static VALUE field_inspect(VALUE obj) {

VALUE n = rb_iv_get(obj, "name");
VALUE s = rb_str_new(0, RSTRING_LEN(n) + 16);
sprintf(RSTRING_PTR(s), "#<Mysql::Field:%s>", RSTRING_PTR(n));
return s;

}

define DefineMysqlFieldMemberMethod(m)\ static VALUE field_##m(VALUE obj)\ {return rb_iv_get(obj, m);}

DefineMysqlFieldMemberMethod(name) DefineMysqlFieldMemberMethod(table) DefineMysqlFieldMemberMethod(def) DefineMysqlFieldMemberMethod(type) DefineMysqlFieldMemberMethod(length) DefineMysqlFieldMemberMethod(max_length) DefineMysqlFieldMemberMethod(flags) DefineMysqlFieldMemberMethod(decimals)

ifdef IS_NUM /* is_num? */ static VALUE field_is_num(VALUE obj) {

return IS_NUM(NUM2INT(rb_iv_get(obj, "type"))) ? Qtrue : Qfalse;

} endif

ifdef IS_NOT_NULL /* is_not_null? */ static VALUE field_is_not_null(VALUE obj) {

return IS_NOT_NULL(NUM2INT(rb_iv_get(obj, "flags"))) ? Qtrue : Qfalse;

} endif

ifdef IS_PRI_KEY /* is_pri_key? */ static VALUE field_is_pri_key(VALUE obj) {

return IS_PRI_KEY(NUM2INT(rb_iv_get(obj, "flags"))) ? Qtrue : Qfalse;

} endif

if MYSQL_VERSION_ID >= 40102 /*——————————-

 Mysql::Stmt object method
/

/* check if stmt is already closed */ static void check_stmt_closed(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
if (s->closed == Qtrue)
    rb_raise(eMysql, "Mysql::Stmt object is already closed");

}

static void mysql_stmt_raise(MYSQL_STMT* s) {

VALUE e = rb_exc_new2(eMysql, mysql_stmt_error(s));
rb_iv_set(e, "errno", INT2FIX(mysql_stmt_errno(s)));
rb_iv_set(e, "sqlstate", rb_tainted_str_new2(mysql_stmt_sqlstate(s)));
rb_exc_raise(e);

}

/* affected_rows() */ static VALUE stmt_affected_rows(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
my_ulonglong n;
check_stmt_closed(obj);
n = mysql_stmt_affected_rows(s->stmt);
return INT2NUM(n);

}

if 0 /* attr_get(option) */ static VALUE stmt_attr_get(VALUE obj, VALUE opt) {

struct mysql_stmt* s = DATA_PTR(obj);
check_stmt_closed(obj);
if (NUM2INT(opt) == STMT_ATTR_UPDATE_MAX_LENGTH) {
    my_bool arg;
    mysql_stmt_attr_get(s->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &arg);
    return arg == 1 ? Qtrue : Qfalse;
}
rb_raise(eMysql, "unknown option: %d", NUM2INT(opt));

}

/* attr_set(option, arg) */ static VALUE stmt_attr_set(VALUE obj, VALUE opt, VALUE val) {

struct mysql_stmt* s = DATA_PTR(obj);
check_stmt_closed(obj);
if (NUM2INT(opt) == STMT_ATTR_UPDATE_MAX_LENGTH) {
    my_bool arg;
    arg = (val == Qnil || val == Qfalse) ? 0 : 1;
    mysql_stmt_attr_set(s->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &arg);
    return obj;
}
rb_raise(eMysql, "unknown option: %d", NUM2INT(opt));

} endif

/* bind_result(bind,…) */ static VALUE stmt_bind_result(int argc, VALUE *argv, VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
int i;
MYSQL_FIELD *field;

check_stmt_closed(obj);
if (argc != s->result.n)
    rb_raise(eMysql, "bind_result: result value count(%d) != number of argument(%d)", s->result.n, argc);
for (i = 0; i < argc; i++) {
    if (argv[i] == Qnil || argv[i] == rb_cNilClass) {
        field = mysql_fetch_fields(s->res);
        s->result.bind[i].buffer_type = field[i].type;
    }
    else if (argv[i] == rb_cString)
        s->result.bind[i].buffer_type = MYSQL_TYPE_STRING;
    else if (argv[i] == rb_cNumeric || argv[i] == rb_cInteger || argv[i] == rb_cFixnum)
        s->result.bind[i].buffer_type = MYSQL_TYPE_LONGLONG;
    else if (argv[i] == rb_cFloat)
        s->result.bind[i].buffer_type = MYSQL_TYPE_DOUBLE;
    else if (argv[i] == cMysqlTime)
        s->result.bind[i].buffer_type = MYSQL_TYPE_DATETIME;
    else
        rb_raise(rb_eTypeError, "unrecognized class: %s", RSTRING_PTR(rb_inspect(argv[i])));
    if (mysql_stmt_bind_result(s->stmt, s->result.bind))
        mysql_stmt_raise(s->stmt);
}
return obj;

}

/* close() */ static VALUE stmt_close(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
check_stmt_closed(obj);
mysql_stmt_close(s->stmt);
s->closed = Qtrue;
return Qnil;

}

/* data_seek(offset) */ static VALUE stmt_data_seek(VALUE obj, VALUE offset) {

struct mysql_stmt* s = DATA_PTR(obj);
check_stmt_closed(obj);
mysql_stmt_data_seek(s->stmt, NUM2INT(offset));
return obj;

}

/* execute(arg,…) */ static VALUE stmt_execute(int argc, VALUE *argv, VALUE obj) {

struct mysql_stmt *s = DATA_PTR(obj);
MYSQL_STMT *stmt = s->stmt;
int i;

check_stmt_closed(obj);
free_execute_memory(s);
if (s->param.n != argc)
    rb_raise(eMysql, "execute: param_count(%d) != number of argument(%d)", s->param.n, argc);
if (argc > 0) {
    memset(s->param.bind, 0, sizeof(*(s->param.bind))*argc);
    for (i = 0; i < argc; i++) {
        switch (TYPE(argv[i])) {
        case T_NIL:
            s->param.bind[i].buffer_type = MYSQL_TYPE_NULL;
            break;
        case T_FIXNUM:

if SIZEOF_INT < SIZEOF_LONG

s->param.bind[i].buffer_type = MYSQL_TYPE_LONGLONG;
s->param.bind[i].buffer = &(s->param.buffer[i]);
 (LONG_LONG*)(s->param.bind[i].buffer) = FIX2LONG(argv[i]);

else

s->param.bind[i].buffer_type = MYSQL_TYPE_LONG;
s->param.bind[i].buffer = &(s->param.buffer[i]);
 (int*)(s->param.bind[i].buffer) = FIX2INT(argv[i]);

endif

            break;
        case T_BIGNUM:
            s->param.bind[i].buffer_type = MYSQL_TYPE_LONGLONG;
            s->param.bind[i].buffer = &(s->param.buffer[i]);
             (LONG_LONG*)(s->param.bind[i].buffer) = rb_big2ll(argv[i]);
            break;
        case T_FLOAT:
            s->param.bind[i].buffer_type = MYSQL_TYPE_DOUBLE;
            s->param.bind[i].buffer = &(s->param.buffer[i]);
             (double*)(s->param.bind[i].buffer) = NUM2DBL(argv[i]);
            break;
        case T_STRING:
            s->param.bind[i].buffer_type = MYSQL_TYPE_STRING;
            s->param.bind[i].buffer = RSTRING_PTR(argv[i]);
            s->param.bind[i].buffer_length = RSTRING_LEN(argv[i]);
            s->param.length[i] = RSTRING_LEN(argv[i]);
            s->param.bind[i].length = &(s->param.length[i]);
            break;
        default:
            if (CLASS_OF(argv[i]) == rb_cTime) {
                MYSQL_TIME t;
                VALUE a = rb_funcall(argv[i], rb_intern("to_a"), 0);
                s->param.bind[i].buffer_type = MYSQL_TYPE_DATETIME;
                s->param.bind[i].buffer = &(s->param.buffer[i]);
                memset(&t, 0, sizeof(t));    /* avoid warning */
                t.second_part = 0;
                t.neg = 0;
                t.second = FIX2INT(RARRAY_PTR(a)[0]);
                t.minute = FIX2INT(RARRAY_PTR(a)[1]);
                t.hour = FIX2INT(RARRAY_PTR(a)[2]);
                t.day = FIX2INT(RARRAY_PTR(a)[3]);
                t.month = FIX2INT(RARRAY_PTR(a)[4]);
                t.year = FIX2INT(RARRAY_PTR(a)[5]);
                t.time_type = MYSQL_TYPE_DATETIME;
                 (MYSQL_TIME*)&(s->param.buffer[i]) = t;
            } else if (CLASS_OF(argv[i]) == cMysqlTime) {
                MYSQL_TIME t;
                s->param.bind[i].buffer_type = MYSQL_TYPE_DATETIME;
                s->param.bind[i].buffer = &(s->param.buffer[i]);
                memset(&t, 0, sizeof(t));    /* avoid warning */
                t.second_part = 0;
                t.neg = 0;
                t.second = NUM2INT(rb_iv_get(argv[i], "second"));
                t.minute = NUM2INT(rb_iv_get(argv[i], "minute"));
                t.hour = NUM2INT(rb_iv_get(argv[i], "hour"));
                t.day = NUM2INT(rb_iv_get(argv[i], "day"));
                t.month = NUM2INT(rb_iv_get(argv[i], "month"));
                t.year = NUM2INT(rb_iv_get(argv[i], "year"));
                t.time_type = MYSQL_TYPE_DATETIME;
                 (MYSQL_TIME*)&(s->param.buffer[i]) = t;
            } else
                rb_raise(rb_eTypeError, "unsupported type: %d", TYPE(argv[i]));
        }
    }
    if (mysql_stmt_bind_param(stmt, s->param.bind))
        mysql_stmt_raise(stmt);
}

if (mysql_stmt_execute(stmt))
    mysql_stmt_raise(stmt);
if (s->res) {
    MYSQL_FIELD *field;
    if (mysql_stmt_store_result(stmt))
        mysql_stmt_raise(stmt);
    field = mysql_fetch_fields(s->res);
    for (i = 0; i < s->result.n; i++) {
        switch(s->result.bind[i].buffer_type) {
        case MYSQL_TYPE_NULL:
            break;
        case MYSQL_TYPE_TINY:
        case MYSQL_TYPE_SHORT:
        case MYSQL_TYPE_YEAR:
        case MYSQL_TYPE_INT24:
        case MYSQL_TYPE_LONG:
        case MYSQL_TYPE_LONGLONG:
        case MYSQL_TYPE_FLOAT:
        case MYSQL_TYPE_DOUBLE:
            s->result.bind[i].buffer = xmalloc(8);
            s->result.bind[i].buffer_length = 8;
            memset(s->result.bind[i].buffer, 0, 8);
            break;
        case MYSQL_TYPE_DECIMAL:
        case MYSQL_TYPE_STRING:
        case MYSQL_TYPE_VAR_STRING:
        case MYSQL_TYPE_TINY_BLOB:
        case MYSQL_TYPE_BLOB:
        case MYSQL_TYPE_MEDIUM_BLOB:
        case MYSQL_TYPE_LONG_BLOB:

if MYSQL_VERSION_ID >= 50003

case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_BIT:

endif

            s->result.bind[i].buffer = xmalloc(field[i].max_length);
            memset(s->result.bind[i].buffer, 0, field[i].max_length);
            s->result.bind[i].buffer_length = field[i].max_length;
            break;
        case MYSQL_TYPE_TIME:
        case MYSQL_TYPE_DATE:
        case MYSQL_TYPE_DATETIME:
        case MYSQL_TYPE_TIMESTAMP:
            s->result.bind[i].buffer = xmalloc(sizeof(MYSQL_TIME));
            s->result.bind[i].buffer_length = sizeof(MYSQL_TIME);
            memset(s->result.bind[i].buffer, 0, sizeof(MYSQL_TIME));
            break;
        default:
            rb_raise(rb_eTypeError, "unknown buffer_type: %d", s->result.bind[i].buffer_type);
        }
    }
    if (mysql_stmt_bind_result(s->stmt, s->result.bind))
        mysql_stmt_raise(s->stmt);
}
return obj;

}

/* fetch() */ static VALUE stmt_fetch(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
VALUE ret;
int i;
int r;

check_stmt_closed(obj);
r = mysql_stmt_fetch(s->stmt);
if (r == MYSQL_NO_DATA)
    return Qnil;

ifdef MYSQL_DATA_TRUNCATED

if (r == MYSQL_DATA_TRUNCATED)
    rb_raise(rb_eRuntimeError, "unexpectedly data truncated");

endif

if (r == 1)
    mysql_stmt_raise(s->stmt);

ret = rb_ary_new2(s->result.n);
for (i = 0; i < s->result.n; i++) {
    if (s->result.is_null[i])
        rb_ary_push(ret, Qnil);
    else {
        VALUE v;
        MYSQL_TIME *t;
        switch (s->result.bind[i].buffer_type) {
        case MYSQL_TYPE_TINY:
            if (s->result.bind[i].is_unsigned)
                v = UINT2NUM(*(unsigned char *)s->result.bind[i].buffer);
            else
                v = INT2NUM(*(signed char *)s->result.bind[i].buffer);
            break;
        case MYSQL_TYPE_SHORT:
        case MYSQL_TYPE_YEAR:
            if (s->result.bind[i].is_unsigned)
                v = UINT2NUM(*(unsigned short *)s->result.bind[i].buffer);
            else
                v = INT2NUM(*(short *)s->result.bind[i].buffer);
            break;
        case MYSQL_TYPE_INT24:
        case MYSQL_TYPE_LONG:
            if (s->result.bind[i].is_unsigned)
                v = UINT2NUM(*(unsigned int *)s->result.bind[i].buffer);
            else
                v = INT2NUM(*(int *)s->result.bind[i].buffer);
            break;
        case MYSQL_TYPE_LONGLONG:
            if (s->result.bind[i].is_unsigned)
                v = ULL2NUM(*(unsigned long long *)s->result.bind[i].buffer);
            else
                v = LL2NUM(*(long long *)s->result.bind[i].buffer);
            break;
        case MYSQL_TYPE_FLOAT:
            v = rb_float_new((double)(*(float *)s->result.bind[i].buffer));
            break;
        case MYSQL_TYPE_DOUBLE:
            v = rb_float_new(*(double *)s->result.bind[i].buffer);
            break;
        case MYSQL_TYPE_TIME:
        case MYSQL_TYPE_DATE:
        case MYSQL_TYPE_DATETIME:
        case MYSQL_TYPE_TIMESTAMP:
            t = (MYSQL_TIME *)s->result.bind[i].buffer;
            v = rb_obj_alloc(cMysqlTime);
            rb_funcall(v, rb_intern("initialize"), 8,
                       INT2FIX(t->year), INT2FIX(t->month),
                       INT2FIX(t->day), INT2FIX(t->hour),
                       INT2FIX(t->minute), INT2FIX(t->second),
                       (t->neg ? Qtrue : Qfalse),
                       INT2FIX(t->second_part));
            break;
        case MYSQL_TYPE_DECIMAL:
        case MYSQL_TYPE_STRING:
        case MYSQL_TYPE_VAR_STRING:
        case MYSQL_TYPE_TINY_BLOB:
        case MYSQL_TYPE_BLOB:
        case MYSQL_TYPE_MEDIUM_BLOB:
        case MYSQL_TYPE_LONG_BLOB:

if MYSQL_VERSION_ID >= 50003

case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_BIT:

endif

            v = rb_tainted_str_new(s->result.bind[i].buffer, s->result.length[i]);
            break;
        default:
            rb_raise(rb_eTypeError, "unknown buffer_type: %d", s->result.bind[i].buffer_type);
        }
        rb_ary_push(ret, v);
    }
}
return ret;

}

/* each {…} */ static VALUE stmt_each(VALUE obj) {

VALUE row;
check_stmt_closed(obj);
while ((row = stmt_fetch(obj)) != Qnil)
    rb_yield(row);
return obj;

}

/* field_count() */ static VALUE stmt_field_count(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
unsigned int n;
check_stmt_closed(obj);
n = mysql_stmt_field_count(s->stmt);
return INT2NUM(n);

}

/* free_result() */ static VALUE stmt_free_result(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
check_stmt_closed(obj);
if (mysql_stmt_free_result(s->stmt))
    mysql_stmt_raise(s->stmt);
return obj;

}

/* insert_id() */ static VALUE stmt_insert_id(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
my_ulonglong n;
check_stmt_closed(obj);
n = mysql_stmt_insert_id(s->stmt);
return ULL2NUM(n);

}

/* num_rows() */ static VALUE stmt_num_rows(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
my_ulonglong n;
check_stmt_closed(obj);
n = mysql_stmt_num_rows(s->stmt);
return INT2NUM(n);

}

/* param_count() */ static VALUE stmt_param_count(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
unsigned long n;
check_stmt_closed(obj);
n = mysql_stmt_param_count(s->stmt);
return INT2NUM(n);

}

/* prepare(query) */ static VALUE stmt_prepare(VALUE obj, VALUE query) {

struct mysql_stmt* s = DATA_PTR(obj);
int n;
int i;
MYSQL_FIELD *field;

free_mysqlstmt_memory(s);
check_stmt_closed(obj);
Check_Type(query, T_STRING);
if (mysql_stmt_prepare(s->stmt, RSTRING_PTR(query), RSTRING_LEN(query)))
    mysql_stmt_raise(s->stmt);

n = mysql_stmt_param_count(s->stmt);
s->param.n = n;
s->param.bind = xmalloc(sizeof(s->param.bind[0]) * n);
s->param.length = xmalloc(sizeof(s->param.length[0]) * n);
s->param.buffer = xmalloc(sizeof(s->param.buffer[0]) * n);

s->res = mysql_stmt_result_metadata(s->stmt);
if (s->res) {
    n = s->result.n = mysql_num_fields(s->res);
    s->result.bind = xmalloc(sizeof(s->result.bind[0]) * n);
    s->result.is_null = xmalloc(sizeof(s->result.is_null[0]) * n);
    s->result.length = xmalloc(sizeof(s->result.length[0]) * n);
    field = mysql_fetch_fields(s->res);
    memset(s->result.bind, 0, sizeof(s->result.bind[0]) * n);
    for (i = 0; i < n; i++) {
        s->result.bind[i].buffer_type = field[i].type;

if MYSQL_VERSION_ID < 50003

if (field[i].type == MYSQL_TYPE_DECIMAL)
    s->result.bind[i].buffer_type = MYSQL_TYPE_STRING;

endif

        s->result.bind[i].is_null = &(s->result.is_null[i]);
        s->result.bind[i].length = &(s->result.length[i]);
        s->result.bind[i].is_unsigned = ((field[i].flags & UNSIGNED_FLAG) != 0);
    }
} else {
    if (mysql_stmt_errno(s->stmt))
        mysql_stmt_raise(s->stmt);
}

return obj;

}

if 0 /* reset() */ static VALUE stmt_reset(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
check_stmt_closed(obj);
if (mysql_stmt_reset(s->stmt))
    mysql_stmt_raise(s->stmt);
return obj;

} endif

/* result_metadata() */ static VALUE stmt_result_metadata(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
MYSQL_RES *res;
check_stmt_closed(obj);
res = mysql_stmt_result_metadata(s->stmt);
if (res == NULL) {
  if (mysql_stmt_errno(s->stmt) != 0)
    mysql_stmt_raise(s->stmt);
  return Qnil;
}
return mysqlres2obj(res);

}

/* row_seek(offset) */ static VALUE stmt_row_seek(VALUE obj, VALUE offset) {

struct mysql_stmt* s = DATA_PTR(obj);
MYSQL_ROW_OFFSET prev_offset;
if (CLASS_OF(offset) != cMysqlRowOffset)
    rb_raise(rb_eTypeError, "wrong argument type %s (expected Mysql::RowOffset)", rb_obj_classname(offset));
check_stmt_closed(obj);
prev_offset = mysql_stmt_row_seek(s->stmt, DATA_PTR(offset));
return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, prev_offset);

}

/* row_tell() */ static VALUE stmt_row_tell(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
MYSQL_ROW_OFFSET offset;
check_stmt_closed(obj);
offset = mysql_stmt_row_tell(s->stmt);
return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, offset);

}

if 0 /* send_long_data(col, data) */ static VALUE stmt_send_long_data(VALUE obj, VALUE col, VALUE data) {

struct mysql_stmt* s = DATA_PTR(obj);
int c;
check_stmt_closed(obj);
c = NUM2INT(col);
if (0 <= c && c < s->param.n) {
    s->param.bind[c].buffer_type = MYSQL_TYPE_STRING;
    if (mysql_stmt_bind_param(s->stmt, s->param.bind))
        mysql_stmt_raise(s->stmt);
}
if (mysql_stmt_send_long_data(s->stmt, c, RSTRING_PTR(data), RSTRING_LEN(data)))
    mysql_stmt_raise(s->stmt);
return obj;

} endif

/* sqlstate() */ static VALUE stmt_sqlstate(VALUE obj) {

struct mysql_stmt* s = DATA_PTR(obj);
return rb_tainted_str_new2(mysql_stmt_sqlstate(s->stmt));

}

/*——————————-

 Mysql::Time object method
/

static VALUE time_initialize(int argc, VALUE* argv, VALUE obj) {

VALUE year, month, day, hour, minute, second, neg, second_part;
rb_scan_args(argc, argv, "08", &year, &month, &day, &hour, &minute, &second, &neg, &second_part);

define NILorFIXvalue(o) (NIL_P(o) ? INT2FIX(0) : (Check_Type(o, T_FIXNUM), o))

rb_iv_set(obj, "year", NILorFIXvalue(year));
rb_iv_set(obj, "month", NILorFIXvalue(month));
rb_iv_set(obj, "day", NILorFIXvalue(day));
rb_iv_set(obj, "hour", NILorFIXvalue(hour));
rb_iv_set(obj, "minute", NILorFIXvalue(minute));
rb_iv_set(obj, "second", NILorFIXvalue(second));
rb_iv_set(obj, "neg", (neg == Qnil || neg == Qfalse) ? Qfalse : Qtrue);
rb_iv_set(obj, "second_part", NILorFIXvalue(second_part));
return obj;

}

static VALUE time_inspect(VALUE obj) {

char buf[36];
sprintf(buf, "#<Mysql::Time:%04ld-%02ld-%02ld %02ld:%02ld:%02ld>",
        NUM2LONG(rb_iv_get(obj, "year")),
        NUM2LONG(rb_iv_get(obj, "month")),
        NUM2LONG(rb_iv_get(obj, "day")),
        NUM2LONG(rb_iv_get(obj, "hour")),
        NUM2LONG(rb_iv_get(obj, "minute")),
        NUM2LONG(rb_iv_get(obj, "second")));
return rb_str_new2(buf);

}

static VALUE time_to_s(VALUE obj) {

char buf[20];
sprintf(buf, "%04ld-%02ld-%02ld %02ld:%02ld:%02ld",
        NUM2LONG(rb_iv_get(obj, "year")),
        NUM2LONG(rb_iv_get(obj, "month")),
        NUM2LONG(rb_iv_get(obj, "day")),
        NUM2LONG(rb_iv_get(obj, "hour")),
        NUM2LONG(rb_iv_get(obj, "minute")),
        NUM2LONG(rb_iv_get(obj, "second")));
return rb_str_new2(buf);

}

define DefineMysqlTimeGetMethod(m)\ static VALUE time_get_##m(VALUE obj)\ {return rb_iv_get(obj, m);}

DefineMysqlTimeGetMethod(year) DefineMysqlTimeGetMethod(month) DefineMysqlTimeGetMethod(day) DefineMysqlTimeGetMethod(hour) DefineMysqlTimeGetMethod(minute) DefineMysqlTimeGetMethod(second) DefineMysqlTimeGetMethod(neg) DefineMysqlTimeGetMethod(second_part)

define DefineMysqlTimeSetMethod(m)\ static VALUE time_set_##m(VALUE obj, VALUE v)\ {rb_iv_set(obj, m, NILorFIXvalue(v)); return v;}

DefineMysqlTimeSetMethod(year) DefineMysqlTimeSetMethod(month) DefineMysqlTimeSetMethod(day) DefineMysqlTimeSetMethod(hour) DefineMysqlTimeSetMethod(minute) DefineMysqlTimeSetMethod(second) DefineMysqlTimeSetMethod(second_part)

static VALUE time_set_neg(VALUE obj, VALUE v) {

rb_iv_set(obj, "neg", (v == Qnil || v == Qfalse) ? Qfalse : Qtrue);
return v;

}

static VALUE time_equal(VALUE obj, VALUE v) {

if (CLASS_OF(v) == cMysqlTime &&
    NUM2INT(rb_iv_get(obj, "year")) == NUM2INT(rb_iv_get(v, "year")) &&
    NUM2INT(rb_iv_get(obj, "month")) == NUM2INT(rb_iv_get(v, "month")) &&
    NUM2INT(rb_iv_get(obj, "day")) == NUM2INT(rb_iv_get(v, "day")) &&
    NUM2INT(rb_iv_get(obj, "hour")) == NUM2INT(rb_iv_get(v, "hour")) &&
    NUM2INT(rb_iv_get(obj, "minute")) == NUM2INT(rb_iv_get(v, "minute")) &&
    NUM2INT(rb_iv_get(obj, "second")) == NUM2INT(rb_iv_get(v, "second")) &&
    rb_iv_get(obj, "neg") == rb_iv_get(v, "neg") &&
    NUM2INT(rb_iv_get(obj, "second_part")) == NUM2INT(rb_iv_get(v, "second_part")))
    return Qtrue;
return Qfalse;

}

endif

/*——————————-

 Mysql::Error object method
/

static VALUE error_error(VALUE obj) {

return rb_iv_get(obj, "mesg");

}

static VALUE error_errno(VALUE obj) {

return rb_iv_get(obj, "errno");

}

static VALUE error_sqlstate(VALUE obj) {

return rb_iv_get(obj, "sqlstate");

}

/*——————————-

      Initialize
/

void Init_mysql(void) {

cMysql = rb_define_class("Mysql", rb_cObject);
cMysqlRes = rb_define_class_under(cMysql, "Result", rb_cObject);
cMysqlField = rb_define_class_under(cMysql, "Field", rb_cObject);

if MYSQL_VERSION_ID >= 40102

cMysqlStmt = rb_define_class_under(cMysql, "Stmt", rb_cObject);
cMysqlRowOffset = rb_define_class_under(cMysql, "RowOffset", rb_cObject);
cMysqlTime = rb_define_class_under(cMysql, "Time", rb_cObject);

endif

eMysql = rb_define_class_under(cMysql, "Error", rb_eStandardError);

rb_define_global_const("MysqlRes", cMysqlRes);
rb_define_global_const("MysqlField", cMysqlField);
rb_define_global_const("MysqlError", eMysql);

/* Mysql class method */
rb_define_singleton_method(cMysql, "init", init, 0);
rb_define_singleton_method(cMysql, "real_connect", real_connect, -1);
rb_define_singleton_method(cMysql, "connect", real_connect, -1);
rb_define_singleton_method(cMysql, "new", real_connect, -1);
rb_define_singleton_method(cMysql, "escape_string", escape_string, 1);
rb_define_singleton_method(cMysql, "quote", escape_string, 1);
rb_define_singleton_method(cMysql, "client_info", client_info, 0);
rb_define_singleton_method(cMysql, "get_client_info", client_info, 0);

if MYSQL_VERSION_ID >= 32332

rb_define_singleton_method(cMysql, "debug", my_debug, 1);

endif if MYSQL_VERSION_ID >= 40000

rb_define_singleton_method(cMysql, "get_client_version", client_version, 0);
rb_define_singleton_method(cMysql, "client_version", client_version, 0);

endif

/* Mysql object method */

if MYSQL_VERSION_ID >= 32200

rb_define_method(cMysql, "real_connect", real_connect2, -1);
rb_define_method(cMysql, "connect", real_connect2, -1);
rb_define_method(cMysql, "options", options, -1);

endif

rb_define_method(cMysql, "initialize", initialize, -1);

if MYSQL_VERSION_ID >= 32332

rb_define_method(cMysql, "escape_string", real_escape_string, 1);
rb_define_method(cMysql, "quote", real_escape_string, 1);

else

rb_define_method(cMysql, "escape_string", escape_string, 1);
rb_define_method(cMysql, "quote", escape_string, 1);

endif

rb_define_method(cMysql, "client_info", client_info, 0);
rb_define_method(cMysql, "get_client_info", client_info, 0);
rb_define_method(cMysql, "affected_rows", affected_rows, 0);

if MYSQL_VERSION_ID >= 32303

rb_define_method(cMysql, "change_user", change_user, -1);

endif if MYSQL_VERSION_ID >= 32321

rb_define_method(cMysql, "character_set_name", character_set_name, 0);

endif

rb_define_method(cMysql, "close", my_close, 0);

if MYSQL_VERSION_ID < 40000

rb_define_method(cMysql, "create_db", create_db, 1);
rb_define_method(cMysql, "drop_db", drop_db, 1);

endif if MYSQL_VERSION_ID >= 32332

rb_define_method(cMysql, "dump_debug_info", dump_debug_info, 0);

endif

rb_define_method(cMysql, "errno", my_errno, 0);
rb_define_method(cMysql, "error", my_error, 0);
rb_define_method(cMysql, "field_count", field_count, 0);

if MYSQL_VERSION_ID >= 40000

rb_define_method(cMysql, "get_client_version", client_version, 0);
rb_define_method(cMysql, "client_version", client_version, 0);

endif

rb_define_method(cMysql, "get_host_info", host_info, 0);
rb_define_method(cMysql, "host_info", host_info, 0);
rb_define_method(cMysql, "get_proto_info", proto_info, 0);
rb_define_method(cMysql, "proto_info", proto_info, 0);
rb_define_method(cMysql, "get_server_info", server_info, 0);
rb_define_method(cMysql, "server_info", server_info, 0);
rb_define_method(cMysql, "info", info, 0);
rb_define_method(cMysql, "insert_id", insert_id, 0);
rb_define_method(cMysql, "kill", my_kill, 1);
rb_define_method(cMysql, "list_dbs", list_dbs, -1);
rb_define_method(cMysql, "list_fields", list_fields, -1);
rb_define_method(cMysql, "list_processes", list_processes, 0);
rb_define_method(cMysql, "list_tables", list_tables, -1);

if MYSQL_VERSION_ID >= 32200

rb_define_method(cMysql, "ping", ping, 0);

endif

rb_define_method(cMysql, "query", query, 1);
rb_define_method(cMysql, "real_query", query, 1);
rb_define_method(cMysql, "refresh", refresh, 1);
rb_define_method(cMysql, "reload", reload, 0);
rb_define_method(cMysql, "select_db", select_db, 1);
rb_define_method(cMysql, "shutdown", my_shutdown, -1);
rb_define_method(cMysql, "stat", my_stat, 0);
rb_define_method(cMysql, "store_result", store_result, 0);
rb_define_method(cMysql, "thread_id", thread_id, 0);
rb_define_method(cMysql, "use_result", use_result, 0);

if MYSQL_VERSION_ID >= 40100

rb_define_method(cMysql, "get_server_version", server_version, 0);
rb_define_method(cMysql, "server_version", server_version, 0);
rb_define_method(cMysql, "warning_count", warning_count, 0);
rb_define_method(cMysql, "commit", commit, 0);
rb_define_method(cMysql, "rollback", rollback, 0);
rb_define_method(cMysql, "autocommit", autocommit, 1);

endif ifdef HAVE_MYSQL_SSL_SET

rb_define_method(cMysql, "ssl_set", ssl_set, -1);

endif if MYSQL_VERSION_ID >= 40102

rb_define_method(cMysql, "stmt_init", stmt_init, 0);
rb_define_method(cMysql, "prepare", prepare, 1);

endif if MYSQL_VERSION_ID >= 40100

rb_define_method(cMysql, "more_results", more_results, 0);
rb_define_method(cMysql, "more_results?", more_results, 0);
rb_define_method(cMysql, "next_result", next_result, 0);

endif if MYSQL_VERSION_ID >= 40101

rb_define_method(cMysql, "set_server_option", set_server_option, 1);
rb_define_method(cMysql, "sqlstate", sqlstate, 0);

endif

rb_define_method(cMysql, "query_with_result", query_with_result, 0);
rb_define_method(cMysql, "query_with_result=", query_with_result_set, 1);

rb_define_method(cMysql, "reconnect", reconnect, 0);
rb_define_method(cMysql, "reconnect=", reconnect_set, 1);

/* Mysql constant */
rb_define_const(cMysql, "VERSION", INT2FIX(MYSQL_RUBY_VERSION));

if MYSQL_VERSION_ID >= 32200

rb_define_const(cMysql, "OPT_CONNECT_TIMEOUT", INT2NUM(MYSQL_OPT_CONNECT_TIMEOUT));
rb_define_const(cMysql, "OPT_COMPRESS", INT2NUM(MYSQL_OPT_COMPRESS));
rb_define_const(cMysql, "OPT_NAMED_PIPE", INT2NUM(MYSQL_OPT_NAMED_PIPE));
rb_define_const(cMysql, "INIT_COMMAND", INT2NUM(MYSQL_INIT_COMMAND));
rb_define_const(cMysql, "READ_DEFAULT_FILE", INT2NUM(MYSQL_READ_DEFAULT_FILE));
rb_define_const(cMysql, "READ_DEFAULT_GROUP", INT2NUM(MYSQL_READ_DEFAULT_GROUP));

endif if MYSQL_VERSION_ID >= 32349

rb_define_const(cMysql, "SET_CHARSET_DIR", INT2NUM(MYSQL_SET_CHARSET_DIR));
rb_define_const(cMysql, "SET_CHARSET_NAME", INT2NUM(MYSQL_SET_CHARSET_NAME));
rb_define_const(cMysql, "OPT_LOCAL_INFILE", INT2NUM(MYSQL_OPT_LOCAL_INFILE));

endif if MYSQL_VERSION_ID >= 40100

rb_define_const(cMysql, "OPT_PROTOCOL", INT2NUM(MYSQL_OPT_PROTOCOL));
rb_define_const(cMysql, "SHARED_MEMORY_BASE_NAME", INT2NUM(MYSQL_SHARED_MEMORY_BASE_NAME));

endif if MYSQL_VERSION_ID >= 40101

rb_define_const(cMysql, "OPT_READ_TIMEOUT", INT2NUM(MYSQL_OPT_READ_TIMEOUT));
rb_define_const(cMysql, "OPT_WRITE_TIMEOUT", INT2NUM(MYSQL_OPT_WRITE_TIMEOUT));
rb_define_const(cMysql, "SECURE_AUTH", INT2NUM(MYSQL_SECURE_AUTH));
rb_define_const(cMysql, "OPT_GUESS_CONNECTION", INT2NUM(MYSQL_OPT_GUESS_CONNECTION));
rb_define_const(cMysql, "OPT_USE_EMBEDDED_CONNECTION", INT2NUM(MYSQL_OPT_USE_EMBEDDED_CONNECTION));
rb_define_const(cMysql, "OPT_USE_REMOTE_CONNECTION", INT2NUM(MYSQL_OPT_USE_REMOTE_CONNECTION));
rb_define_const(cMysql, "SET_CLIENT_IP", INT2NUM(MYSQL_SET_CLIENT_IP));

endif

rb_define_const(cMysql, "REFRESH_GRANT", INT2NUM(REFRESH_GRANT));
rb_define_const(cMysql, "REFRESH_LOG", INT2NUM(REFRESH_LOG));
rb_define_const(cMysql, "REFRESH_TABLES", INT2NUM(REFRESH_TABLES));

ifdef REFRESH_HOSTS

rb_define_const(cMysql, "REFRESH_HOSTS", INT2NUM(REFRESH_HOSTS));

endif ifdef REFRESH_STATUS

rb_define_const(cMysql, "REFRESH_STATUS", INT2NUM(REFRESH_STATUS));

endif ifdef REFRESH_THREADS

rb_define_const(cMysql, "REFRESH_THREADS", INT2NUM(REFRESH_THREADS));

endif ifdef REFRESH_SLAVE

rb_define_const(cMysql, "REFRESH_SLAVE", INT2NUM(REFRESH_SLAVE));

endif ifdef REFRESH_MASTER

rb_define_const(cMysql, "REFRESH_MASTER", INT2NUM(REFRESH_MASTER));

endif ifdef CLIENT_LONG_PASSWORD endif ifdef CLIENT_FOUND_ROWS

rb_define_const(cMysql, "CLIENT_FOUND_ROWS", INT2NUM(CLIENT_FOUND_ROWS));

endif ifdef CLIENT_LONG_FLAG endif ifdef CLIENT_CONNECT_WITH_DB endif ifdef CLIENT_NO_SCHEMA

rb_define_const(cMysql, "CLIENT_NO_SCHEMA", INT2NUM(CLIENT_NO_SCHEMA));

endif ifdef CLIENT_COMPRESS

rb_define_const(cMysql, "CLIENT_COMPRESS", INT2NUM(CLIENT_COMPRESS));

endif ifdef CLIENT_ODBC

rb_define_const(cMysql, "CLIENT_ODBC", INT2NUM(CLIENT_ODBC));

endif ifdef CLIENT_LOCAL_FILES

rb_define_const(cMysql, "CLIENT_LOCAL_FILES", INT2NUM(CLIENT_LOCAL_FILES));

endif ifdef CLIENT_IGNORE_SPACE

rb_define_const(cMysql, "CLIENT_IGNORE_SPACE", INT2NUM(CLIENT_IGNORE_SPACE));

endif ifdef CLIENT_CHANGE_USER

rb_define_const(cMysql, "CLIENT_CHANGE_USER", INT2NUM(CLIENT_CHANGE_USER));

endif ifdef CLIENT_INTERACTIVE

rb_define_const(cMysql, "CLIENT_INTERACTIVE", INT2NUM(CLIENT_INTERACTIVE));

endif ifdef CLIENT_SSL

rb_define_const(cMysql, "CLIENT_SSL", INT2NUM(CLIENT_SSL));

endif ifdef CLIENT_IGNORE_SIGPIPE

rb_define_const(cMysql, "CLIENT_IGNORE_SIGPIPE", INT2NUM(CLIENT_IGNORE_SIGPIPE));

endif ifdef CLIENT_TRANSACTIONS

rb_define_const(cMysql, "CLIENT_TRANSACTIONS", INT2NUM(CLIENT_TRANSACTIONS));

endif ifdef CLIENT_MULTI_STATEMENTS

rb_define_const(cMysql, "CLIENT_MULTI_STATEMENTS", INT2NUM(CLIENT_MULTI_STATEMENTS));

endif ifdef CLIENT_MULTI_RESULTS

rb_define_const(cMysql, "CLIENT_MULTI_RESULTS", INT2NUM(CLIENT_MULTI_RESULTS));

endif if MYSQL_VERSION_ID >= 40101

rb_define_const(cMysql, "OPTION_MULTI_STATEMENTS_ON", INT2NUM(MYSQL_OPTION_MULTI_STATEMENTS_ON));
rb_define_const(cMysql, "OPTION_MULTI_STATEMENTS_OFF", INT2NUM(MYSQL_OPTION_MULTI_STATEMENTS_OFF));

endif

/* Mysql::Result object method */
rb_define_method(cMysqlRes, "data_seek", data_seek, 1);
rb_define_method(cMysqlRes, "fetch_field", fetch_field, 0);
rb_define_method(cMysqlRes, "fetch_fields", fetch_fields, 0);
rb_define_method(cMysqlRes, "fetch_field_direct", fetch_field_direct, 1);
rb_define_method(cMysqlRes, "fetch_lengths", fetch_lengths, 0);
rb_define_method(cMysqlRes, "fetch_row", fetch_row, 0);
rb_define_method(cMysqlRes, "fetch_hash", fetch_hash, -1);
rb_define_method(cMysqlRes, "field_seek", field_seek, 1);
rb_define_method(cMysqlRes, "field_tell", field_tell, 0);
rb_define_method(cMysqlRes, "free", res_free, 0);
rb_define_method(cMysqlRes, "num_fields", num_fields, 0);
rb_define_method(cMysqlRes, "num_rows", num_rows, 0);
rb_define_method(cMysqlRes, "row_seek", row_seek, 1);
rb_define_method(cMysqlRes, "row_tell", row_tell, 0);
rb_define_method(cMysqlRes, "each", each, 0);
rb_define_method(cMysqlRes, "each_hash", each_hash, -1);

/* MysqlField object method */
rb_define_method(cMysqlField, "name", field_name, 0);
rb_define_method(cMysqlField, "table", field_table, 0);
rb_define_method(cMysqlField, "def", field_def, 0);
rb_define_method(cMysqlField, "type", field_type, 0);
rb_define_method(cMysqlField, "length", field_length, 0);
rb_define_method(cMysqlField, "max_length", field_max_length, 0);
rb_define_method(cMysqlField, "flags", field_flags, 0);
rb_define_method(cMysqlField, "decimals", field_decimals, 0);
rb_define_method(cMysqlField, "hash", field_hash, 0);
rb_define_method(cMysqlField, "inspect", field_inspect, 0);

ifdef IS_NUM

rb_define_method(cMysqlField, "is_num?", field_is_num, 0);

endif ifdef IS_NOT_NULL

rb_define_method(cMysqlField, "is_not_null?", field_is_not_null, 0);

endif ifdef IS_PRI_KEY

rb_define_method(cMysqlField, "is_pri_key?", field_is_pri_key, 0);

endif

/* Mysql::Field constant: TYPE */
rb_define_const(cMysqlField, "TYPE_TINY", INT2NUM(FIELD_TYPE_TINY));

if MYSQL_VERSION_ID >= 32115

rb_define_const(cMysqlField, "TYPE_ENUM", INT2NUM(FIELD_TYPE_ENUM));

endif

rb_define_const(cMysqlField, "TYPE_DECIMAL", INT2NUM(FIELD_TYPE_DECIMAL));
rb_define_const(cMysqlField, "TYPE_SHORT", INT2NUM(FIELD_TYPE_SHORT));
rb_define_const(cMysqlField, "TYPE_LONG", INT2NUM(FIELD_TYPE_LONG));
rb_define_const(cMysqlField, "TYPE_FLOAT", INT2NUM(FIELD_TYPE_FLOAT));
rb_define_const(cMysqlField, "TYPE_DOUBLE", INT2NUM(FIELD_TYPE_DOUBLE));
rb_define_const(cMysqlField, "TYPE_NULL", INT2NUM(FIELD_TYPE_NULL));
rb_define_const(cMysqlField, "TYPE_TIMESTAMP", INT2NUM(FIELD_TYPE_TIMESTAMP));
rb_define_const(cMysqlField, "TYPE_LONGLONG", INT2NUM(FIELD_TYPE_LONGLONG));
rb_define_const(cMysqlField, "TYPE_INT24", INT2NUM(FIELD_TYPE_INT24));
rb_define_const(cMysqlField, "TYPE_DATE", INT2NUM(FIELD_TYPE_DATE));
rb_define_const(cMysqlField, "TYPE_TIME", INT2NUM(FIELD_TYPE_TIME));
rb_define_const(cMysqlField, "TYPE_DATETIME", INT2NUM(FIELD_TYPE_DATETIME));

if MYSQL_VERSION_ID >= 32130

rb_define_const(cMysqlField, "TYPE_YEAR", INT2NUM(FIELD_TYPE_YEAR));

endif if MYSQL_VERSION_ID >= 50003

rb_define_const(cMysqlField, "TYPE_BIT", INT2NUM(FIELD_TYPE_BIT));
rb_define_const(cMysqlField, "TYPE_NEWDECIMAL", INT2NUM(FIELD_TYPE_NEWDECIMAL));

endif

rb_define_const(cMysqlField, "TYPE_SET", INT2NUM(FIELD_TYPE_SET));
rb_define_const(cMysqlField, "TYPE_BLOB", INT2NUM(FIELD_TYPE_BLOB));
rb_define_const(cMysqlField, "TYPE_STRING", INT2NUM(FIELD_TYPE_STRING));

if MYSQL_VERSION_ID >= 40000

rb_define_const(cMysqlField, "TYPE_VAR_STRING", INT2NUM(FIELD_TYPE_VAR_STRING));

endif

rb_define_const(cMysqlField, "TYPE_CHAR", INT2NUM(FIELD_TYPE_CHAR));

/* Mysql::Field constant: FLAG */
rb_define_const(cMysqlField, "NOT_NULL_FLAG", INT2NUM(NOT_NULL_FLAG));
rb_define_const(cMysqlField, "PRI_KEY_FLAG", INT2NUM(PRI_KEY_FLAG));
rb_define_const(cMysqlField, "UNIQUE_KEY_FLAG", INT2NUM(UNIQUE_KEY_FLAG));
rb_define_const(cMysqlField, "MULTIPLE_KEY_FLAG", INT2NUM(MULTIPLE_KEY_FLAG));
rb_define_const(cMysqlField, "BLOB_FLAG", INT2NUM(BLOB_FLAG));
rb_define_const(cMysqlField, "UNSIGNED_FLAG", INT2NUM(UNSIGNED_FLAG));
rb_define_const(cMysqlField, "ZEROFILL_FLAG", INT2NUM(ZEROFILL_FLAG));
rb_define_const(cMysqlField, "BINARY_FLAG", INT2NUM(BINARY_FLAG));

ifdef ENUM_FLAG

rb_define_const(cMysqlField, "ENUM_FLAG", INT2NUM(ENUM_FLAG));

endif ifdef AUTO_INCREMENT_FLAG

rb_define_const(cMysqlField, "AUTO_INCREMENT_FLAG", INT2NUM(AUTO_INCREMENT_FLAG));

endif ifdef TIMESTAMP_FLAG

rb_define_const(cMysqlField, "TIMESTAMP_FLAG", INT2NUM(TIMESTAMP_FLAG));

endif ifdef SET_FLAG

rb_define_const(cMysqlField, "SET_FLAG", INT2NUM(SET_FLAG));

endif ifdef NUM_FLAG

rb_define_const(cMysqlField, "NUM_FLAG", INT2NUM(NUM_FLAG));

endif ifdef PART_KEY_FLAG

rb_define_const(cMysqlField, "PART_KEY_FLAG", INT2NUM(PART_KEY_FLAG));

endif

if MYSQL_VERSION_ID >= 40102

/* Mysql::Stmt object method */
rb_define_method(cMysqlStmt, "affected_rows", stmt_affected_rows, 0);

if 0

rb_define_method(cMysqlStmt, "attr_get", stmt_attr_get, 1);
rb_define_method(cMysqlStmt, "attr_set", stmt_attr_set, 2);

endif

rb_define_method(cMysqlStmt, "bind_result", stmt_bind_result, -1);
rb_define_method(cMysqlStmt, "close", stmt_close, 0);
rb_define_method(cMysqlStmt, "data_seek", stmt_data_seek, 1);
rb_define_method(cMysqlStmt, "each", stmt_each, 0);
rb_define_method(cMysqlStmt, "execute", stmt_execute, -1);
rb_define_method(cMysqlStmt, "fetch", stmt_fetch, 0);
rb_define_method(cMysqlStmt, "field_count", stmt_field_count, 0);
rb_define_method(cMysqlStmt, "free_result", stmt_free_result, 0);
rb_define_method(cMysqlStmt, "insert_id", stmt_insert_id, 0);
rb_define_method(cMysqlStmt, "num_rows", stmt_num_rows, 0);
rb_define_method(cMysqlStmt, "param_count", stmt_param_count, 0);
rb_define_method(cMysqlStmt, "prepare", stmt_prepare, 1);

if 0

rb_define_method(cMysqlStmt, "reset", stmt_reset, 0);

endif

rb_define_method(cMysqlStmt, "result_metadata", stmt_result_metadata, 0);
rb_define_method(cMysqlStmt, "row_seek", stmt_row_seek, 1);
rb_define_method(cMysqlStmt, "row_tell", stmt_row_tell, 0);

if 0

rb_define_method(cMysqlStmt, "send_long_data", stmt_send_long_data, 2);

endif

rb_define_method(cMysqlStmt, "sqlstate", stmt_sqlstate, 0);

if 0

rb_define_const(cMysqlStmt, "ATTR_UPDATE_MAX_LENGTH", INT2NUM(STMT_ATTR_UPDATE_MAX_LENGTH));

endif

/* Mysql::Time object method */
rb_define_method(cMysqlTime, "initialize", time_initialize, -1);
rb_define_method(cMysqlTime, "inspect", time_inspect, 0);
rb_define_method(cMysqlTime, "to_s", time_to_s, 0);
rb_define_method(cMysqlTime, "year", time_get_year, 0);
rb_define_method(cMysqlTime, "month", time_get_month, 0);
rb_define_method(cMysqlTime, "day", time_get_day, 0);
rb_define_method(cMysqlTime, "hour", time_get_hour, 0);
rb_define_method(cMysqlTime, "minute", time_get_minute, 0);
rb_define_method(cMysqlTime, "second", time_get_second, 0);
rb_define_method(cMysqlTime, "neg", time_get_neg, 0);
rb_define_method(cMysqlTime, "second_part", time_get_second_part, 0);
rb_define_method(cMysqlTime, "year=", time_set_year, 1);
rb_define_method(cMysqlTime, "month=", time_set_month, 1);
rb_define_method(cMysqlTime, "day=", time_set_day, 1);
rb_define_method(cMysqlTime, "hour=", time_set_hour, 1);
rb_define_method(cMysqlTime, "minute=", time_set_minute, 1);
rb_define_method(cMysqlTime, "second=", time_set_second, 1);
rb_define_method(cMysqlTime, "neg=", time_set_neg, 1);
rb_define_method(cMysqlTime, "second_part=", time_set_second_part, 1);
rb_define_method(cMysqlTime, "==", time_equal, 1);

endif

/* Mysql::Error object method */
rb_define_method(eMysql, "error", error_error, 0);
rb_define_method(eMysql, "errno", error_errno, 0);
rb_define_method(eMysql, "sqlstate", error_sqlstate, 0);

/* Mysql::Error constant */

define rb_define_mysql_const(s) rb_define_const(eMysql, s, INT2NUM(s)) include “error_const.h” }