Skip to content

Commit b12be74

Browse files
nyaxtjustincase
authored andcommitted
raise stmt errors via rb_raise_mysql2_stmt_error
1 parent 744f1af commit b12be74

File tree

3 files changed

+68
-14
lines changed

3 files changed

+68
-14
lines changed

ext/mysql2/result.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,11 @@ static VALUE rb_mysql_result_stmt_fetch_row(VALUE self, ID db_timezone, ID app_t
317317
}
318318

319319
if(mysql_stmt_bind_result(wrapper->stmt, wrapper->result_buffers)) {
320-
321-
rb_raise(cMysql2Error, "%s", mysql_stmt_error(wrapper->stmt));
320+
rb_raise_mysql2_stmt_error2(wrapper->stmt
321+
#ifdef HAVE_RUBY_ENCODING_H
322+
, conn_enc
323+
#endif
324+
);
322325
}
323326

324327
if(mysql_stmt_fetch(wrapper->stmt)) {

ext/mysql2/statement.c

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22

33
VALUE cMysql2Statement;
44
extern VALUE mMysql2, cMysql2Error, cBigDecimal, cDateTime, cDate;
5-
static VALUE sym_stream;
5+
static VALUE sym_stream, intern_error_number_eql, intern_sql_state_eql;
6+
7+
#define GET_STATEMENT(self) \
8+
mysql_stmt_wrapper *stmt_wrapper; \
9+
Data_Get_Struct(self, mysql_stmt_wrapper, stmt_wrapper);
10+
611

712
static void rb_mysql_stmt_mark(void * ptr) {
813
mysql_stmt_wrapper* stmt_wrapper = (mysql_stmt_wrapper *)ptr;
@@ -19,6 +24,49 @@ static void rb_mysql_stmt_free(void * ptr) {
1924
xfree(ptr);
2025
}
2126

27+
VALUE rb_raise_mysql2_stmt_error2(MYSQL_STMT *stmt
28+
#ifdef HAVE_RUBY_ENCODING_H
29+
, rb_encoding *conn_enc
30+
#endif
31+
) {
32+
VALUE rb_error_msg = rb_str_new2(mysql_stmt_error(stmt));
33+
VALUE rb_sql_state = rb_tainted_str_new2(mysql_stmt_sqlstate(stmt));
34+
#ifdef HAVE_RUBY_ENCODING_H
35+
rb_encoding *default_internal_enc = rb_default_internal_encoding();
36+
37+
rb_enc_associate(rb_error_msg, conn_enc);
38+
rb_enc_associate(rb_sql_state, conn_enc);
39+
if (default_internal_enc) {
40+
rb_error_msg = rb_str_export_to_enc(rb_error_msg, default_internal_enc);
41+
rb_sql_state = rb_str_export_to_enc(rb_sql_state, default_internal_enc);
42+
}
43+
#endif
44+
45+
VALUE e = rb_exc_new3(cMysql2Error, rb_error_msg);
46+
rb_funcall(e, intern_error_number_eql, 1, UINT2NUM(mysql_stmt_errno(stmt)));
47+
rb_funcall(e, intern_sql_state_eql, 1, rb_sql_state);
48+
rb_exc_raise(e);
49+
return Qnil;
50+
}
51+
52+
static void rb_raise_mysql2_stmt_error(VALUE self) {
53+
#ifdef HAVE_RUBY_ENCODING_H
54+
rb_encoding *conn_enc;
55+
#endif
56+
GET_STATEMENT(self);
57+
{
58+
GET_CLIENT(stmt_wrapper->client);
59+
conn_enc = rb_to_encoding(wrapper->encoding);
60+
}
61+
62+
rb_raise_mysql2_stmt_error2(stmt_wrapper->stmt
63+
#ifdef HAVE_RUBY_ENCODING_H
64+
, conn_enc
65+
#endif
66+
);
67+
}
68+
69+
2270
/*
2371
* used to pass all arguments to mysql_stmt_prepare while inside
2472
* nogvl_prepare_statement_args
@@ -88,18 +136,13 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
88136
args.sql_len = RSTRING_LEN(sql);
89137

90138
if ((VALUE)rb_thread_call_without_gvl(nogvl_prepare_statement, &args, RUBY_UBF_IO, 0) == Qfalse) {
91-
rb_raise(cMysql2Error, "%s", mysql_stmt_error(stmt_wrapper->stmt));
139+
rb_raise_mysql2_stmt_error(rb_stmt);
92140
}
93141
}
94142

95143
return rb_stmt;
96144
}
97145

98-
#define GET_STATEMENT(self) \
99-
mysql_stmt_wrapper *stmt_wrapper; \
100-
Data_Get_Struct(self, mysql_stmt_wrapper, stmt_wrapper)
101-
102-
103146
/* call-seq: stmt.param_count # => Numeric
104147
*
105148
* Returns the number of parameters the prepared statement expects.
@@ -275,13 +318,13 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
275318
// copies bind_buffers into internal storage
276319
if (mysql_stmt_bind_param(stmt, bind_buffers)) {
277320
FREE_BINDS;
278-
rb_raise(cMysql2Error, "%s", mysql_stmt_error(stmt));
321+
rb_raise_mysql2_stmt_error(self);
279322
}
280323
}
281324

282325
if ((VALUE)rb_thread_call_without_gvl(nogvl_execute, stmt, RUBY_UBF_IO, 0) == Qfalse) {
283326
FREE_BINDS;
284-
rb_raise(cMysql2Error, "%s", mysql_stmt_error(stmt));
327+
rb_raise_mysql2_stmt_error(self);
285328
}
286329

287330
FREE_BINDS;
@@ -292,7 +335,7 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
292335
// either CR_OUT_OF_MEMORY or CR_UNKNOWN_ERROR. both fatal.
293336

294337
MARK_CONN_INACTIVE(stmt_wrapper->client);
295-
rb_raise(cMysql2Error, "%s", mysql_stmt_error(stmt));
338+
rb_raise_mysql2_stmt_error(self);
296339
}
297340
// no data and no error, so query was not a SELECT
298341
return Qnil;
@@ -307,7 +350,7 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) {
307350
} else {
308351
// recieve the whole result set from the server
309352
if (rb_thread_call_without_gvl(nogvl_stmt_store_result, stmt, RUBY_UBF_IO, 0) == Qfalse) {
310-
rb_raise(cMysql2Error, "%s", mysql_stmt_error(stmt));
353+
rb_raise_mysql2_stmt_error(self);
311354
}
312355
MARK_CONN_INACTIVE(stmt_wrapper->client);
313356
}
@@ -384,4 +427,7 @@ void init_mysql2_statement() {
384427
rb_define_method(cMysql2Statement, "fields", fields, 0);
385428

386429
sym_stream = ID2SYM(rb_intern("stream"));
430+
431+
intern_error_number_eql = rb_intern("error_number=");
432+
intern_sql_state_eql = rb_intern("sql_state=");
387433
}

ext/mysql2/statement.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@ void init_mysql2_statement();
77

88
typedef struct {
99
VALUE client;
10-
MYSQL_STMT* stmt;
10+
MYSQL_STMT *stmt;
1111
} mysql_stmt_wrapper;
1212

1313
VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql);
14+
VALUE rb_raise_mysql2_stmt_error2(MYSQL_STMT *stmt
15+
#ifdef HAVE_RUBY_ENCODING_H
16+
, rb_encoding* conn_enc
17+
#endif
18+
);
1419

1520
#endif

0 commit comments

Comments
 (0)